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:
parent
dc7de148c3
commit
cb93a65449
@ -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);
|
||||
|
@ -17,6 +17,7 @@ MergeObject posix_unistd.o :
|
||||
hostname.cpp
|
||||
ioctl.c
|
||||
link.c
|
||||
lockf.cpp
|
||||
lseek.c
|
||||
mknod.c
|
||||
mount.c
|
||||
|
85
src/system/libroot/posix/unistd/lockf.cpp
Normal file
85
src/system/libroot/posix/unistd/lockf.cpp
Normal 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."
|
||||
}
|
Loading…
Reference in New Issue
Block a user