Mail Archives: djgpp-workers/2000/12/29/21:21:12
--=====================_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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <strings.h>
+#include <dos.h>
+#include <libc/dosio.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <strings.h>
+#include <dos.h>
+#include <libc/dosio.h>
+
+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 <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+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 <unistd.h>
+
+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 <unistd.h> 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 <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+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 <unistd.h>
+
+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 <unistd.h> 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 <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+
+/* 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 <sys/file.h>
+
+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==_--
- Raw text -