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:
@@ -21,6 +21,12 @@
|
|||||||
#define STDOUT_FILENO 1
|
#define STDOUT_FILENO 1
|
||||||
#define STDERR_FILENO 2
|
#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 */
|
/* POSIX version support */
|
||||||
#define _POSIX_VERSION (199009L)
|
#define _POSIX_VERSION (199009L)
|
||||||
|
|
||||||
@@ -111,7 +117,8 @@ extern int getdtablesize(void);
|
|||||||
extern long sysconf(int name);
|
extern long sysconf(int name);
|
||||||
extern long fpathconf(int fd, int name);
|
extern long fpathconf(int fd, int name);
|
||||||
extern long pathconf(const char *path, 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 */
|
/* process functions */
|
||||||
extern pid_t fork(void);
|
extern pid_t fork(void);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ MergeObject posix_unistd.o :
|
|||||||
hostname.cpp
|
hostname.cpp
|
||||||
ioctl.c
|
ioctl.c
|
||||||
link.c
|
link.c
|
||||||
|
lockf.cpp
|
||||||
lseek.c
|
lseek.c
|
||||||
mknod.c
|
mknod.c
|
||||||
mount.c
|
mount.c
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Vasilis Kaoutsis, [email protected].
|
||||||
|
* 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."
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user