Message-Id: <5.0.2.1.0.20001229205411.00a53560@pop5.banet.net> X-Sender: usbanet DOT farley3 AT pop5 DOT banet DOT net X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 Date: Fri, 29 Dec 2000 20:55:31 -0500 To: djgpp-workers AT delorie DOT com From: "Peter J. Farley III" Subject: RE: fcntl locking changes #3: new functions flock/lockf/llockf Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_11067657==_" Reply-To: djgpp-workers AT delorie DOT com --=====================_11067657==_ Content-Type: text/plain; charset="us-ascii"; format=flowed And then I forgot to put in the patch. I *really* have to get more sleep, Real Soon Now. This is the right subject, right patch -- the prior flock patch left out the flock function, now included. Sorry again for the confusion. --=====================_11067657==_ Content-Type: text/plain; charset="us-ascii" diff -ruN djgpp-cvs/include/sys/file.h djgpp/include/sys/file.h --- djgpp-cvs/include/sys/file.h Thu Apr 20 01:35:34 1995 +++ djgpp/include/sys/file.h Mon Dec 11 21:56:46 2000 @@ -22,6 +22,18 @@ #define L_CURR 1 #define L_INCR 1 #define L_XTND 2 + +/* Operations for the `flock' call. */ +#define LOCK_SH 1 /* Shared lock. */ +#define LOCK_EX 2 /* Exclusive lock. */ +#define LOCK_UN 8 /* Unlock. */ + +/* Can be OR'd in to one of the above. */ +#define LOCK_NB 4 /* Don't block when locking. */ + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int flock (int _fildes, int _op); #ifndef __dj_ENFORCE_FUNCTION_CALLS #endif /* !__dj_ENFORCE_FUNCTION_CALLS */ diff -ruN djgpp-cvs/include/unistd.h djgpp/include/unistd.h --- djgpp-cvs/include/unistd.h Fri Dec 29 04:48:04 2000 +++ djgpp/include/unistd.h Fri Dec 29 06:22:08 2000 @@ -18,7 +18,16 @@ #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 - + +/* `lockf' is a simpler interface to the locking facilities of `fcntl'. + LEN is always relative to the current file position. + The CMD argument is one of the following. */ + +# define F_ULOCK 0 /* Unlock a previously locked region. */ +# define F_LOCK 1 /* Lock a region for exclusive use. */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ +# define F_TEST 3 /* Test a region for other processes locks. */ + /* Some programs think they know better... */ #undef NULL @@ -61,7 +70,7 @@ #define _SC_TZNAME_MAX 9 #define _SC_VERSION 10 -#ifndef _SIZE_T +#ifndef _SIZE_T __DJ_size_t #define _SIZE_T #endif @@ -138,6 +147,8 @@ int getpagesize(void); char * getwd(char *__buffer); int lchown(const char * file, int owner, int group); +int lockf(int _fildes, int _cmd, off_t _len); +int llockf(int _fildes, int _cmd, offset_t _len); offset_t llseek(int _fildes, offset_t _offset, int _whence); int nice(int _increment); int readlink(const char * __file, char * __buffer, size_t __size); diff -ruN djgpp-cvs/tests/libc/compat/unistd/makefile djgpp/tests/libc/compat/unistd/makefile --- djgpp-cvs/tests/libc/compat/unistd/makefile Fri Aug 25 07:37:10 2000 +++ djgpp/tests/libc/compat/unistd/makefile Mon Dec 11 21:56:52 2000 @@ -3,6 +3,8 @@ SRC += readlink.c SRC += sdirlink.c SRC += symlink.c +SRC += tlockf.c +SRC += tllockf.c SRC += xsymlink.c include $(TOP)/../makefile.inc diff -ruN djgpp-cvs/tests/libc/compat/unistd/tllockf.c djgpp/tests/libc/compat/unistd/tllockf.c --- djgpp-cvs/tests/libc/compat/unistd/tllockf.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/compat/unistd/tllockf.c Mon Dec 11 21:56:52 2000 @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + printf("DOS extended error to errno: %i : %s\n", + __doserr_to_errno(de.exterror),strerror(__doserr_to_errno(de.exterror))); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +int main(void) { + int retval, fd; + + fd = open("tllockf.c", O_RDONLY); + + errno = 0; + retval = llockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_TLOCK, 0); + printf("F_TLOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_TLOCK, 0); + printf("F_TLOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_LOCK, 0); + printf("F_LOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = llockf(fd, F_LOCK, 0); + printf("F_LOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_LOCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = llockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = llockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + close(fd); + exit(0); +} diff -ruN djgpp-cvs/tests/libc/compat/unistd/tllockf.ok djgpp/tests/libc/compat/unistd/tllockf.ok --- djgpp-cvs/tests/libc/compat/unistd/tllockf.ok Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/compat/unistd/tllockf.ok Fri Dec 29 05:15:40 2000 @@ -0,0 +1,48 @@ +F_TEST:retval=0 +F_TLOCK:retval=0 +F_TLOCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_TEST:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_ULOCK:retval=0 +F_ULOCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_TEST:retval=0 +F_LOCK:retval=0 +F_LOCK:Bypassed to avoid lockup in endless loop. +F_TEST:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_ULOCK:retval=0 +F_TEST:retval=0 diff -ruN djgpp-cvs/tests/libc/compat/unistd/tlockf.c djgpp/tests/libc/compat/unistd/tlockf.c --- djgpp-cvs/tests/libc/compat/unistd/tlockf.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/compat/unistd/tlockf.c Mon Dec 11 21:56:52 2000 @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + printf("DOS extended error to errno: %i : %s\n", + __doserr_to_errno(de.exterror),strerror(__doserr_to_errno(de.exterror))); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +int main(void) { + int retval, fd; + + fd = open("tlockf.c", O_RDONLY); + + errno = 0; + retval = lockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_TLOCK, 0); + printf("F_TLOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_TLOCK, 0); + printf("F_TLOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_LOCK, 0); + printf("F_LOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = lockf(fd, F_LOCK, 0); + printf("F_LOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_LOCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = lockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_ULOCK, 0); + printf("F_ULOCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = lockf(fd, F_TEST, 0); + printf("F_TEST:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + close(fd); + exit(0); +} diff -ruN djgpp-cvs/tests/libc/compat/unistd/tlockf.ok djgpp/tests/libc/compat/unistd/tlockf.ok --- djgpp-cvs/tests/libc/compat/unistd/tlockf.ok Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/compat/unistd/tlockf.ok Fri Dec 29 05:15:32 2000 @@ -0,0 +1,48 @@ +F_TEST:retval=0 +F_TLOCK:retval=0 +F_TLOCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_TEST:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_ULOCK:retval=0 +F_ULOCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_TEST:retval=0 +F_LOCK:retval=0 +F_LOCK:Bypassed to avoid lockup in endless loop. +F_TEST:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_ULOCK:retval=0 +F_TEST:retval=0 diff -ruN djgpp-cvs/src/libc/compat/unistd/llockf.c djgpp/src/libc/compat/unistd/llockf.c --- djgpp-cvs/src/libc/compat/unistd/llockf.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/compat/unistd/llockf.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,55 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +#include +#include +#include +#include +#include + +int +llockf (int _fildes, int _cmd, offset_t _len) +{ + struct flock64 lock_req; + + memset ((char *) &lock_req, '\0', sizeof (lock_req)); + + /* lockf is always relative to the current file position. */ + lock_req.l_whence = SEEK_CUR; + lock_req.l_start = 0L; + lock_req.l_len = _len; + + switch (_cmd) + { + case F_TEST: + lock_req.l_type = F_WRLCK; + /* Test the lock: return 0 if FD is unlocked; + return -1, set errno to EACCES, if the lock cannot be obtained. */ + if (fcntl (_fildes, F_GETLK64, &lock_req) < 0) + return -1; + if (lock_req.l_type == F_UNLCK) + return 0; + errno = EACCES; + return -1; + + case F_ULOCK: + lock_req.l_type = F_UNLCK; + _cmd = F_SETLK64; + break; + case F_LOCK: + lock_req.l_type = F_WRLCK; + _cmd = F_SETLKW64; + break; + case F_TLOCK: + lock_req.l_type = F_WRLCK; + _cmd = F_SETLK64; + break; + + default: + errno = EINVAL; + return -1; + } + + return fcntl (_fildes, _cmd, &lock_req); +} diff -ruN djgpp-cvs/src/libc/compat/unistd/llockf.txh djgpp/src/libc/compat/unistd/llockf.txh --- djgpp-cvs/src/libc/compat/unistd/llockf.txh Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/compat/unistd/llockf.txh Sat Dec 16 01:20:20 2000 @@ -0,0 +1,128 @@ +@node llockf, unistd +@subheading Syntax + +@example +#include + +int llockf (int fildes, int function, offset_t size); +@end example + +@subheading Description + +The @code{llockf} command is a simplified interface to the locking +facilities of @code{fcntl} (see @ref{fcntl} for more detailed +information). + +The @code{llockf} command performs exactly the same functions as +@code{lockf} (see @pxref{lockf}), with exactly the same input commands +and results, but the input @var{size} parameter is of type +@code{offset_t} instead of @code{off_t}, and the @code{fcntl} calls are +made using functions @code{F_GETLK64}, @code{F_SETLK64} and +@code{F_SETLKW64}, where @code{lockf} uses functions @code{F_GETLK}, +@code{F_SETLK} and @code{F_SETLKW}. + +The @code{llockf} command is intended to permit using @code{fcntl} +functions with @var{size} values greater than @math{2^31 - 1}. + +@var{fildes} is an open file descriptor. + +@var{function} is a control value which specifies the action to be +taken. The permissible values for function are defined in as +follows: + +@example +#define F_ULOCK 0 /* Unlock a previously locked section */ +#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 section for other locks */ +@end example + +All other values of @var{function} are reserved for future extensions +and will result in an error return if not implemented, with @code{errno} +set to @code{EINVAL}. + +@var{size} is the number of contiguous bytes to be locked or unlocked. +The resource to be locked starts at the current offset in the file and +extends forward for a positive @var{size} and backward for a negative +@var{size} (the preceding bytes up to but not including the current +offset). If @var{size} is zero, the section from the current offset +through the largest file offset is locked (i.e., from the current offset +through the end-of-file). + +The functions defined for @code{llockf} are as follows: + +@table @code +@item F_TEST +This function is used to detect if the specified section is already +locked. + +@itemx F_LOCK +@itemx F_TLOCK +@code{F_LOCK} and @code{F_TLOCK} both lock a section of a file, if the +section is available. These two function requests differ only by the +action taken if the resource is not available. @code{F_LOCK} will cause +the calling program to wait until the resource is available. +@code{F_TLOCK} will cause the function to return a -1 and set +@code{errno} to error @code{EACCES} if the section is already locked. + +@itemx F_ULOCK +@code{F_ULOCK} removes locks from a section of the file. This function +will release locked sections controlled by the program. +@end table + +The @code{llockf} command will fail, returning -1 and setting +@code{errno} to the following error values if the associated condition +is true: + +@table @code +@item EBADF +Parameter @var{fildes} is not a valid open file. + +@itemx EACCES +Parameter @var{function} is @code{F_TLOCK} or @code{F_TEST} and the +section is already locked. + +@itemx EINVAL +Parameter @var{function} is not one of the implemented functions. +@end table + +All lock requests in this implementation are coded as exclusive locks +(i.e., all locks use the @code{fcntl} request @code{F_WRLCK}). + +It is therefore wise to code @code{llockf} by using function +@code{F_TLOCK} with all lock requests, and to test the return value to +determine if the lock was obtained or not. Using @code{F_TLOCK} will +cause the implementation to use @code{F_SETLK} instead of +@code{F_SETLKW}, which will return an error if the lock cannot be +obtained. + + +@subheading Return Value + +On success, zero is returned. On error, -1 is returned, and +@code{errno} is set appropriately, as described above. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example + /* Request a lock on file handle fd from the current position to + the end of the file */ + errno = 0; + retval = llockf(fd, F_LOCK, 0); + + /* Request a non-blocking lock on file handle fd */ + errno = 0; + retval = llockf(fd, F_TLOCK, 0); + + /* Test a lock on file handle fd */ + errno = 0; + retval = llockf(fd, F_TEST, 0); + + /* Release a lock on file handle fd */ + errno = 0; + retval = llockf(fd, F_ULOCK, 0); +@end example diff -ruN djgpp-cvs/src/libc/compat/unistd/lockf.c djgpp/src/libc/compat/unistd/lockf.c --- djgpp-cvs/src/libc/compat/unistd/lockf.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/compat/unistd/lockf.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,55 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +#include +#include +#include +#include +#include + +int +lockf (int _fildes, int _cmd, off_t _len) +{ + struct flock lock_req; + + memset ((char *) &lock_req, '\0', sizeof (lock_req)); + + /* lockf is always relative to the current file position. */ + lock_req.l_whence = SEEK_CUR; + lock_req.l_start = 0; + lock_req.l_len = _len; + + switch (_cmd) + { + case F_TEST: + lock_req.l_type = F_WRLCK; + /* Test the lock: return 0 if FD is unlocked; + return -1, set errno to EACCES, if the lock cannot be obtained. */ + if (fcntl (_fildes, F_GETLK, &lock_req) < 0) + return -1; + if (lock_req.l_type == F_UNLCK) + return 0; + errno = EACCES; + return -1; + + case F_ULOCK: + lock_req.l_type = F_UNLCK; + _cmd = F_SETLK; + break; + case F_LOCK: + lock_req.l_type = F_WRLCK; + _cmd = F_SETLKW; + break; + case F_TLOCK: + lock_req.l_type = F_WRLCK; + _cmd = F_SETLK; + break; + + default: + errno = EINVAL; + return -1; + } + + return fcntl (_fildes, _cmd, &lock_req); +} diff -ruN djgpp-cvs/src/libc/compat/unistd/lockf.txh djgpp/src/libc/compat/unistd/lockf.txh --- djgpp-cvs/src/libc/compat/unistd/lockf.txh Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/compat/unistd/lockf.txh Tue Dec 12 22:58:50 2000 @@ -0,0 +1,117 @@ +@node lockf, unistd +@subheading Syntax + +@example +#include + +int lockf (int fildes, int function, off_t size); +@end example + +@subheading Description + +The @code{lockf} command is a simplified interface to the locking +facilities of @code{fcntl} (see @ref{fcntl} for more detailed +information). + +@var{fildes} is an open file descriptor. + +@var{function} is a control value which specifies the action to be +taken. The permissible values for function are defined in as +follows: + +@example +#define F_ULOCK 0 /* Unlock a previously locked section */ +#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 section for other locks */ +@end example + +All other values of @var{function} are reserved for future extensions +and will result in an error return if not implemented, with @code{errno} +set to @code{EINVAL}. + +@var{size} is the number of contiguous bytes to be locked or unlocked. +The resource to be locked starts at the current offset in the file and +extends forward for a positive @var{size} and backward for a negative +@var{size} (the preceding bytes up to but not including the current +offset). If @var{size} is zero, the section from the current offset +through the largest file offset is locked (i.e., from the current offset +through the end-of-file). + +The functions defined for @code{lockf} are as follows: + +@table @code +@item F_TEST +This function is used to detect if the specified section is already +locked. + +@itemx F_LOCK +@itemx F_TLOCK +@code{F_LOCK} and @code{F_TLOCK} both lock a section of a file, if the +section is available. These two function requests differ only by the +action taken if the resource is not available. @code{F_LOCK} will cause +the calling program to wait until the resource is available. +@code{F_TLOCK} will cause the function to return a -1 and set +@code{errno} to error @code{EACCES} if the section is already locked. + +@itemx F_ULOCK +@code{F_ULOCK} removes locks from a section of the file. This function +will release locked sections controlled by the program. +@end table + +The @code{lockf} command will fail, returning -1 and setting +@code{errno} to the following error values if the associated condition +is true: + +@table @code +@item EBADF +Parameter @var{fildes} is not a valid open file. + +@itemx EACCES +Parameter @var{function} is @code{F_TLOCK} or @code{F_TEST} and the +section is already locked. + +@itemx EINVAL +Parameter @var{function} is not one of the implemented functions. +@end table + +All lock requests in this implementation are coded as exclusive locks +(i.e., all locks use the @code{fcntl} request @code{F_WRLCK}). + +It is therefore wise to code @code{lockf} by using function +@code{F_TLOCK} with all lock requests, and to test the return value to +determine if the lock was obtained or not. Using @code{F_TLOCK} will +cause the implementation to use @code{F_SETLK} instead of +@code{F_SETLKW}, which will return an error if the lock cannot be +obtained. + + +@subheading Return Value + +On success, zero is returned. On error, -1 is returned, and +@code{errno} is set appropriately, as described above. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example + /* Request a lock on file handle fd from the current position to + the end of the file */ + errno = 0; + retval = lockf(fd, F_LOCK, 0); + + /* Request a non-blocking lock on file handle fd */ + errno = 0; + retval = lockf(fd, F_TLOCK, 0); + + /* Test a lock on file handle fd */ + errno = 0; + retval = lockf(fd, F_TEST, 0); + + /* Release a lock on file handle fd */ + errno = 0; + retval = lockf(fd, F_ULOCK, 0); +@end example diff -ruN djgpp-cvs/src/libc/compat/unistd/makefile djgpp/src/libc/compat/unistd/makefile --- djgpp-cvs/src/libc/compat/unistd/makefile Fri Aug 25 07:35:36 2000 +++ djgpp/src/libc/compat/unistd/makefile Mon Dec 11 21:56:58 2000 @@ -13,6 +13,8 @@ SRC += getwd.c SRC += lchown.c SRC += llseek.c +SRC += lockf.c +SRC += llockf.c SRC += nice.c SRC += readlink.c SRC += sdirlink.c diff -ruN djgpp-cvs/src/libc/posix/sys/file/flock.c djgpp/src/libc/posix/sys/file/flock.c --- djgpp-cvs/src/libc/posix/sys/file/flock.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/posix/sys/file/flock.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,38 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + +/* This file implements the `flock' function in terms of the POSIX.1 `fcntl' + locking mechanism. */ + +#include +#include +#include +#include + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int +flock (int _fildes, int _op) +{ + struct flock lock_req; + + switch (_op & ~LOCK_NB) + { + case LOCK_SH: + lock_req.l_type = F_RDLCK; + break; + case LOCK_EX: + lock_req.l_type = F_WRLCK; + break; + case LOCK_UN: + lock_req.l_type = F_UNLCK; + break; + default: + errno = EINVAL; + return -1; + } + + lock_req.l_whence = SEEK_SET; + lock_req.l_start = lock_req.l_len = 0L; /* Lock the whole file. */ + + return fcntl (_fildes, (_op & LOCK_NB) ? F_SETLK : F_SETLKW, &lock_req); +} diff -ruN djgpp-cvs/src/libc/posix/sys/file/flock.txh djgpp/src/libc/posix/sys/file/flock.txh --- djgpp-cvs/src/libc/posix/sys/file/flock.txh Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/posix/sys/file/flock.txh Mon Dec 11 21:56:58 2000 @@ -0,0 +1,89 @@ +@node flock, sys +@subheading Syntax + +@example +#include + +int flock (int _fildes, int _op); +@end example + +@subheading Description + +Apply or remove an advisory lock on an open file. The file is specified +by file handle @var{_fildes}. Valid operations are given below: + +@table @code +@item LOCK_SH +Shared lock. More than one process may hold a shared lock for a given +file at a given time. + +However, all locks on DOS/Win9x are exclusive locks, so @code{LOCK_SH} +requests are treated as if they were @code{LOCK_EX} requests. + +@item LOCK_EX +Exclusive lock. Only one process may hold an exclusive lock for a given +file at a given time. + +@item LOCK_UN +Unlock the file. + +@item LOCK_NB +Don't block when locking. May be specified (by or'ing) along with one of +the other operations. +@end table + +On other systems, a single file may not simultaneously have both shared +and exclusive locks. However, on DOS/Win9x, all locks are exclusive +locks, so this rule is not true for DOS/Win9x. + +A file is locked, not the file descriptor. So, dup (2) does not create +multiple instances of a lock. + +Dos/Win9x does not support shared locks, but the underlying +implementation (which uses the @code{F_SETLK} (non-blocking) or +@code{F_SETLKW} (blocking) commands to @code{fcntl}, see @ref{fcntl}) +translates all shared lock request into exclusive lock requests. Thus, +requests for shared locks will be treated as if exclusive locks were +requested, and only one lock will ever be permitted at any one time on +any specified region of the file. + +It is therefore wise to code @code{flock} by or'ing @code{LOCK_NB} with +all lock requests, whether shared or exclusive, and to test the return +value to determine if the lock was obtained or not. Using +@code{LOCK_NB} will cause the implementation to use @code{F_SETLK} +instead of @code{F_SETLKW}, which will return an error if the lock +cannot be obtained. + +@subheading Return Value + +On success, zero is returned. On error, -1 is returned, and +@code{errno} is set appropriately. + +@subheading Portability + +@port-note posix 4.4BSD (the flock (2) call first appeared in 4.2BSD). +@portability !ansi, posix + +@subheading Example + +@example + /* Request a shared lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_SH); + + /* Request a non-blocking shared lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_SH | LOCK_NB); + + /* Request an exclusive lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_EX); + + /* Request a non-blocking exclusive lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_EX | LOCK_NB); + + /* Release a lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_UN); +@end example diff -ruN djgpp-cvs/src/libc/posix/sys/file/makefile djgpp/src/libc/posix/sys/file/makefile --- djgpp-cvs/src/libc/posix/sys/file/makefile Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/posix/sys/file/makefile Mon Dec 11 21:56:58 2000 @@ -0,0 +1,6 @@ +# Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += flock.c + +include $(TOP)/../makefile.inc --=====================_11067657==_ Content-Type: text/plain; charset="us-ascii"; format=flowed --------------------------------------------------------- Peter J. Farley III (pjfarley AT dorsai DOT org OR pjfarley AT banet DOT net) --=====================_11067657==_--