Patch by Vasilis Kaoutsis: Added and implemented lockf() using fcntl() locking.

Small change and notes on standard compliance by myself.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22628 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-10-20 19:51:49 +00:00
parent dc7de148c3
commit cb93a65449
3 changed files with 94 additions and 1 deletions

View File

@ -21,6 +21,12 @@
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
/* function arguments needed by lockf() */
#define F_ULOCK 0 /* unlock locked sections */
#define F_LOCK 1 /* lock a section for exclusive use */
#define F_TLOCK 2 /* test and lock a section for exclusive use */
#define F_TEST 3 /* test a section for locks by other processes */
/* POSIX version support */
#define _POSIX_VERSION (199009L)
@ -111,7 +117,8 @@ extern int getdtablesize(void);
extern long sysconf(int name);
extern long fpathconf(int fd, int name);
extern long pathconf(const char *path, int name);
extern size_t confstr(int name, char *buf, size_t len);
extern size_t confstr(int name, char *buf, size_t len);
extern int lockf(int fd, int function, off_t size);
/* process functions */
extern pid_t fork(void);

View File

@ -17,6 +17,7 @@ MergeObject posix_unistd.o :
hostname.cpp
ioctl.c
link.c
lockf.cpp
lseek.c
mknod.c
mount.c

View File

@ -0,0 +1,85 @@
/*
* Copyright 2007, Vasilis Kaoutsis, kaoutsis@sch.gr.
* Distributed under the terms of the MIT License.
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int
lockf(int fileDescriptor, int function, off_t size)
{
struct flock fileLock;
fileLock.l_start = 0;
fileLock.l_len = size;
fileLock.l_whence = SEEK_CUR;
if (function == F_ULOCK) {
// unlock locked sections
fileLock.l_type = F_UNLCK;
return fcntl(fileDescriptor, F_SETLK, &fileLock);
} else if (function == F_LOCK) {
// lock a section for exclusive use
fileLock.l_type = F_WRLCK;
return fcntl(fileDescriptor, F_SETLKW, &fileLock);
} else if (function == F_TLOCK) {
// test and lock a section for exclusive use
fileLock.l_type = F_WRLCK;
return fcntl(fileDescriptor, F_SETLK, &fileLock);
} else if (function == F_TEST) {
// test a section for locks by other processes
fileLock.l_type = F_WRLCK;
if (fcntl(fileDescriptor, F_GETLK, &fileLock) == -1)
return -1;
if (fileLock.l_type == F_UNLCK)
return 0;
errno = EAGAIN;
return -1;
} else {
errno = EINVAL;
return -1;
}
// Notes regarding standard compliance (cf. Open Group Base Specs):
// * "The interaction between fcntl() and lockf() locks is unspecified."
// * fcntl() locking works on a per-process level. The lockf() description
// is a little fuzzy on whether it works the same way. The first quote
// seem to describe per-thread locks (though it might actually mean
// "threads of other processes"), but the others quotes are strongly
// indicating per-process locks:
// - "Calls to lockf() from other threads which attempt to lock the locked
// file section shall either return an error value or block until the
// section becomes unlocked."
// - "All the locks for a process are removed when the process
// terminates."
// - "F_TEST shall detect if a lock by another process is present on the
// specified section."
// - "The sections locked with F_LOCK or F_TLOCK may, in whole or in part,
// contain or be contained by a previously locked section for the same
// process. When this occurs, or if adjacent locked sections would
// occur, the sections shall be combined into a single locked section."
// * fcntl() and lockf() handle a 0 size argument differently. The former
// use the file size at the time of the call:
// "If the command is F_SETLKW and the process must wait for another
// process to release a lock, then the range of bytes to be locked shall
// be determined before the fcntl() function blocks. If the file size
// or file descriptor seek offset change while fcntl() is blocked, this
// shall not affect the range of bytes locked."
// lockf(), on the other hand, is supposed to create a lock whose size
// dynamically adjusts to the file size:
// "If size is 0, the section from the current offset through the largest
// possible file offset shall be locked (that is, from the current
// offset through the present or any future end-of-file)."
// * The lock release handling when closing descriptors sounds a little
// different, though might actually mean the same.
// For fcntl():
// "All locks associated with a file for a given process shall be removed
// when a file descriptor for that file is closed by that process or the
// process holding that file descriptor terminates."
// For lockf():
// "File locks shall be released on first close by the locking process of
// any file descriptor for the file."
}