[bug #4302] errno is not always an extern int
[mmh] / sbr / lock_file.c
index 9771543..6deddd4 100644 (file)
@@ -3,11 +3,34 @@
  * lock.c -- routines to lock/unlock files
  *
  * $Id$
+ *
+ * This code is Copyright (c) 2002, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
  */
 
+/* Modified by Ruud de Rooij to support Miquel van Smoorenburg's liblockfile
+ *
+ * Since liblockfile locking shares most of its code with dot locking, it
+ * is enabled by defining both DOT_LOCKING and HAVE_LIBLOCKFILE.
+ *
+ * Ruud de Rooij <ruud@debian.org>  Sun, 28 Mar 1999 15:34:03 +0200
+ */
 #include <h/mh.h>
 #include <h/signals.h>
 
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef TM_IN_SYS_TIME
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
 #ifdef HAVE_ERRNO_H
 # include <errno.h>
 #endif
@@ -29,7 +52,9 @@
 
 #include <signal.h>
 
-extern int errno;
+#if defined(HAVE_LIBLOCKFILE)
+#include <lockfile.h>
+#endif
 
 #ifdef LOCKDIR
 char *lockdir = LOCKDIR;
@@ -45,7 +70,9 @@ char *lockdir = LOCKDIR;
 /* struct for getting name of lock file to create */
 struct lockinfo {
     char curlock[BUFSIZ];
+#if !defined(HAVE_LIBLOCKFILE)
     char tmplock[BUFSIZ];
+#endif
 };
 
 /*
@@ -54,11 +81,13 @@ struct lockinfo {
  */
 #define        NSECS 20
 
+#if !defined(HAVE_LIBLOCKFILE)
 /*
  * How old does a lock file need to be
  * before we remove it.
  */
 #define RSECS 180
+#endif /* HAVE_LIBLOCKFILE */
 
 /* struct for recording and updating locks */
 struct lock {
@@ -145,9 +174,13 @@ lkclose (int fd, char *file)
 
 #ifdef DOT_LOCKING
     lockname (file, &lkinfo, 0);       /* get name of lock file */
+#if !defined(HAVE_LIBLOCKFILE)
     unlink (lkinfo.curlock);           /* remove lock file      */
+#else
+    lockfile_remove(lkinfo.curlock);
+#endif /* HAVE_LIBLOCKFILE */
     timerOFF (fd);                     /* turn off lock timer   */
-#endif
+#endif /* DOT_LOCKING */
 
     return (close (fd));
 }
@@ -166,10 +199,22 @@ lkfopen (char *file, char *mode)
 
     if (strcmp (mode, "r") == 0)
        access = O_RDONLY;
-    else
+    else if (strcmp (mode, "r+") == 0)
        access = O_RDWR;
+    else if (strcmp (mode, "w") == 0)
+       access = O_WRONLY | O_CREAT | O_TRUNC;
+    else if (strcmp (mode, "w+") == 0)
+       access = O_RDWR | O_CREAT | O_TRUNC;
+    else if (strcmp (mode, "a") == 0)
+       access = O_WRONLY | O_CREAT | O_APPEND;
+    else if (strcmp (mode, "a+") == 0)
+       access = O_RDWR | O_CREAT | O_APPEND;
+    else {
+       errno = EINVAL;
+       return NULL;
+    }
 
-    if ((fd = lkopen (file, access, 0)) == -1)
+    if ((fd = lkopen (file, access, 0666)) == -1)
        return NULL;
 
     if ((fp = fdopen (fd, mode)) == NULL) {
@@ -220,9 +265,13 @@ lkfclose (FILE *fp, char *file)
 
 #ifdef DOT_LOCKING
     lockname (file, &lkinfo, 0);       /* get name of lock file */
+#if !defined(HAVE_LIBLOCKFILE)
     unlink (lkinfo.curlock);           /* remove lock file      */
+#else
+    lockfile_remove(lkinfo.curlock);
+#endif /* HAVE_LIBLOCKFILE */
     timerOFF (fileno(fp));             /* turn off lock timer   */
-#endif
+#endif /* DOT_LOCKING */
 
     return (fclose (fp));
 }
@@ -275,7 +324,8 @@ lkopen_kernel (char *file, int access, mode_t mode)
 # endif
 
 # ifdef FLOCK_LOCKING
-       if (flock (fd, LOCK_EX | LOCK_NB) != -1)
+       if (flock (fd, (((access & 03) == O_RDONLY) ? LOCK_SH : LOCK_EX)
+                  | LOCK_NB) != -1)
            return fd;
 # endif
 
@@ -325,6 +375,7 @@ lkopen_dot (char *file, int access, mode_t mode)
      */
     lockname (file, &lkinfo, 1);
 
+#if !defined(HAVE_LIBLOCKFILE)
     for (i = 0;;) {
        /* attempt to create lock file */
        if (lockit (&lkinfo) == 0) {
@@ -352,8 +403,19 @@ lkopen_dot (char *file, int access, mode_t mode)
            }
        }
     }
+#else
+    if (lockfile_create(lkinfo.curlock, 5, 0) == L_SUCCESS) {
+        timerON(lkinfo.curlock, fd);
+        return fd;
+    }
+    else {
+        close(fd);
+        return -1;
+    }
+#endif /* HAVE_LIBLOCKFILE */
 }
 
+#if !defined(HAVE_LIBLOCKFILE)
 /*
  * Routine that actually tries to create
  * the lock file.
@@ -372,9 +434,18 @@ lockit (struct lockinfo *li)
     curlock = li->curlock;
     tmplock = li->tmplock;
 
+#ifdef HAVE_MKSTEMP
+    if ((fd = mkstemp(tmplock)) == -1)
+       return -1;
+#else
+    if (mktemp(tmplock) == NULL)
+       return -1;
+    if (unlink(tmplock) == -1 && errno != ENOENT)
+       return -1;
     /* create the temporary lock file */
     if ((fd = creat(tmplock, 0600)) == -1)
        return -1;
+#endif
 
 #if 0
     /* write our process id into lock file */
@@ -393,6 +464,7 @@ lockit (struct lockinfo *li)
 
     return (fd == -1 ? -1 : 0);
 }
+#endif /* HAVE_LIBLOCKFILE */
 
 /*
  * Get name of lock file, and temporary lock file
@@ -442,6 +514,7 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
 
     snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp);
 
+#if !defined(HAVE_LIBLOCKFILE)
     /*
      * If this is for a new lock, create a name for
      * the temporary lock file for lockit()
@@ -452,14 +525,8 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
        else
            snprintf (li->tmplock, sizeof(li->tmplock), "%.*s,LCK.XXXXXX",
                     cp - li->curlock, li->curlock);
-#ifdef HAVE_MKSTEMP
-       mkstemp (li->tmplock);
-#else
-       mktemp (li->tmplock);
-#endif
-
-       unlink (li->tmplock);   /* remove any stray */
     }
+#endif
 }
 
 
@@ -549,8 +616,12 @@ alrmser (int sig)
     /* update the ctime of all the lock files */
     for (lp = l_top; lp; lp = lp->l_next) {
        lockfile = lp->l_lock;
+#if !defined(HAVE_LIBLOCKFILE)
        if (*lockfile && (j = creat (lockfile, 0600)) != -1)
            close (j);
+#else
+    lockfile_touch(lockfile);
+#endif
     }
 
     /* restart the alarm */