[PATCH]: Add flock syscall emulation

Nicholas Wourms nwourms@netscape.net
Thu Nov 27 19:51:00 GMT 2003


Hi All,

Here is a patch to add the flock() syscall to Cygwin.  I've noticed that some
of our mailer apps are using this syscall and have encountered a number of
other apps which do as well.  In most cases, they will provide an emulation of
flock using fcntl() in the case that  flock() is absent from the system's libc.
I've also noticed that some Linux distributions, Red Hat in particular, do not
trust the Linux kernel's implementation of flock and thus prefer to emulate it
in a similar manner.

Rather then duplicate the numerous varieties of emulated flock out there, I
decided to port this particular version of flock emulation from a patch
written by a Red Hat employee for use in Red Hat's IMAPd RPM.  I tried
contacting the individual listed in the spec's ChangeLog, but got no response.
IANAL, but since there was no notice of copyright at the top of the file and
since this code was created for Red Hat by a Red Hat employee, I'm assuming
that Red Hat owns the rights to this code?  This is based on the assumption
that Red Hat employees sign a similar copyright assignment to the one that we
do.  If this isn't so, please let me know and I'll go back to the drawing board.

So, I tweaked the code and formatting for use by Cygwin and have updated the
sys/file.h header to support the operations provided by this syscall.  I based
that off of the header from FreeBSD, which also resulted in the other changes.
IMHO, I found that the comments and the way in which the alternative whence
values were defined in the BSD header seemed to add more clarity.  So if there
are no objections, I thought I'd add those changes as well.

Also, I added an underscore symbol in the case that some program was looking
for the BSD syscall.  It was mostly done as an after-thought, so feel free to
dump that if you are inclined to do so.

Lastly, for testing purposes, you can build the flock source as an executable.
This is just a very small test to prove basic flock() functionality.  I've
tested successfully using some of the tests in the LTP.  Also, I've been
running programs using this implementation for months now, with no adverse
side-effects.

As a side note, I noticed that sys/file.h was from DJGPP.  Will DJ allow us to
use code from DJGPP in Newlib/Cygwin?  If so, I noticed some code in the DJGPP
libc which I could port and use in future contributions.

Cheers,
Nicholas
-------------- next part --------------
2003-11-27  Nicholas Wourms  <nwourms@netscape.net>

	* Makefile.in: (DLL_OFILES): Add flock.o.
	* cygwin.din: Export flock & _flock.
	* flock.c: New file.
	* include/sys/file.h: Include sys/cdefs.h.
	Add function prototype for flock().
	Add some comments from BSD's header for further clarity.
	(L_SET, L_CURR, L_INCR, L_XTND): Redefine as the macros
	SEEK_SET, SEEK_CUR, SEEK_CUR, & SEEK_END respectively.
	(LOCK_SH,LOCK_EX,LOCK_NB,LOCK_UN): New macros for flock().
	* include/cygwin/version.h: Bump API minor number.
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/Makefile.in,v
retrieving revision 1.143
diff -u -3 -p -r1.143 Makefile.in
--- Makefile.in	27 Oct 2003 13:06:56 -0000	1.143
+++ Makefile.in	27 Nov 2003 18:42:44 -0000
@@ -126,8 +126,8 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o
 	fhandler_random.o fhandler_raw.o fhandler_registry.o fhandler_serial.o \
 	fhandler_socket.o fhandler_tape.o fhandler_termios.o \
 	fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
-	fhandler_zero.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o init.o \
-	ioctl.o ipc.o iruserok.o localtime.o malloc_wrapper.o miscfuncs.o \
+	fhandler_zero.o flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o \
+	init.o ioctl.o ipc.o iruserok.o localtime.o malloc_wrapper.o miscfuncs.o \
 	mmap.o msg.o net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o \
 	poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o registry.o \
 	resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
Index: cygwin.din
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/cygwin.din,v
retrieving revision 1.104
diff -u -3 -p -r1.104 cygwin.din
--- cygwin.din	19 Nov 2003 18:50:20 -0000	1.104
+++ cygwin.din	27 Nov 2003 18:32:19 -0000
@@ -504,6 +517,8 @@ finitef
 _finitef = finitef
 fiprintf
 _fiprintf = fiprintf
+flock
+_flock = flock
 floor
 _floor = floor
 floorf
Index: flock.c
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/flock.c,v
retrieving revision 1.0
diff -u -3 -p -r1.0 flock.c
--- flock.c	1970-01-01 01:00:00.000000000 +0100
+++ flock.c	2003-11-27 13:22:48.000000000 -0500
@@ -0,0 +1,80 @@
+/* One of many ways to emulate flock() on top of real (good) POSIX locks.
+ *
+ * This flock() emulation is based upon source taken from the Red Hat
+ * implimentation used in their imap-2002d SRPM.
+ *
+ * $RH: flock.c,v 1.2 2000/08/23 17:07:00 nalin Exp $
+ */
+/* flock.c
+
+   Copyright 2003 Red Hat, Inc.
+
+   This file is part of Cygwin.
+
+   This software is a copyrighted work licensed under the terms of the
+   Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+   details. */
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+_DEFUN (flock, (fd, operation),
+	int fd _AND
+	int operation)
+{
+	int i, cmd;
+	struct flock l = {0, 0, 0, 0, 0};
+	if(operation & LOCK_NB) {
+		cmd = F_SETLK;
+	} else {
+		cmd = F_SETLKW;
+	}
+	l.l_whence = SEEK_SET;
+	switch(operation & (~LOCK_NB)) {
+		case LOCK_EX:
+			l.l_type = F_WRLCK;
+			i = fcntl(fd, cmd, &l);
+			if(i == -1) {
+				if((errno == EAGAIN) || (errno == EACCES)) {
+					errno = EWOULDBLOCK;
+				}
+			}
+			break;
+		case LOCK_SH:
+			l.l_type = F_RDLCK;
+			i = fcntl(fd, cmd, &l);
+			if(i == -1) {
+				if((errno == EAGAIN) || (errno == EACCES)) {
+					errno = EWOULDBLOCK;
+				}
+			}
+			break;
+		case LOCK_UN:
+			l.l_type = F_UNLCK;
+			i = fcntl(fd, cmd, &l);
+			if(i == -1) {
+				if((errno == EAGAIN) || (errno == EACCES)) {
+					errno = EWOULDBLOCK;
+				}
+			}
+			break;
+		default:
+			i = -1;
+			errno = EINVAL;
+			break;
+	}
+	return i; 
+}
+
+#ifdef FLOCK_EMULATE_IS_MAIN
+int main(int argc, char **argv)
+{
+	int fd = open(argv[1], O_WRONLY);
+	flock(fd, LOCK_EX);
+	return 0;
+}
+#endif
Index: include/sys/file.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/sys/file.h,v
retrieving revision 1.6
diff -u -3 -p -r1.6 file.h
--- include/sys/file.h	8 May 2001 01:36:50 -0000	1.6
+++ include/sys/file.h	27 Nov 2003 18:28:10 -0000
@@ -11,20 +11,35 @@
 ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
-
 #ifndef _FILE_H_
 #define _FILE_H_
 
+#include <sys/cdefs.h>
 #include <fcntl.h>
 
-#define L_SET  0
-#define L_CURR 1
-#define L_INCR 1
-#define L_XTND 2
+/* Whence values for lseek(); renamed by POSIX 1003.1 */
+#define L_SET		SEEK_SET
+#define L_CURR		SEEK_CUR
+#define L_INCR		SEEK_CUR
+#define L_XTND		SEEK_END
+
+/* Operations for flock() function */
+#define	LOCK_SH		1	/* Shared lock. */
+#define	LOCK_EX		2	/* Exclusive lock. */
+#define	LOCK_NB		4	/* Don't block when locking. */
+#define	LOCK_UN		8	/* Unlock. */
 
+/* Operations for access function */
 #define	F_OK		0	/* does file exist */
-#define X_OK		1	/* is it executable by caller */
+#define X_OK		1	/* is it executable or searchable by caller */
 #define	W_OK		2	/* is it writable by caller */
 #define	R_OK		4	/* is it readable by caller */
+
+/* Apply or remove an advisory lock on the file fd refers to. */
+__BEGIN_DECLS
+
+int	_EXFUN(flock, (int, int));
+
+__END_DECLS
 
 #endif
Index: include/cygwin/version.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/cygwin/version.h,v
retrieving revision 1.146
diff -u -3 -p -r1.146 version.h
--- include/cygwin/version.h	19 Nov 2003 18:50:22 -0000	1.146
+++ include/cygwin/version.h	27 Nov 2003 18:36:53 -0000
@@ -229,13 +229,14 @@ details. */
       102: CW_GET_UID_FROM_SID and CW_GET_GID_FROM_SID addition to external.cc.
       103: Export getprogname, setprogname.
       104: Export msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop.
+      105: Export flock, _flock.
 
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 104
+#define CYGWIN_VERSION_API_MINOR 105
 
      /* There is also a compatibity version number associated with the
 	shared memory regions.  It is incremented when incompatible


More information about the Cygwin-patches mailing list