X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/2d5d9e243c91784909b11948894e3ba0989107c0..8699f1cc:/sbr/lock_file.c?ds=sidebyside diff --git a/sbr/lock_file.c b/sbr/lock_file.c index 71a559c6..2c8b1c75 100644 --- a/sbr/lock_file.c +++ b/sbr/lock_file.c @@ -1,6 +1,4 @@ - -/* - * lock.c -- routines to lock/unlock files +/* lock_file.c -- routines to lock/unlock files * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for @@ -19,6 +17,8 @@ #include #include #include +#include "lock_file.h" +#include "m_mktemp.h" #ifdef HAVE_SYS_TIME_H # include @@ -73,15 +73,9 @@ struct lock { enum locktype { FCNTL_LOCKING, FLOCK_LOCKING, LOCKF_LOCKING, DOT_LOCKING }; -/* - * Flags to indicate whether we've initialized the lock types, and - * our saved lock types - */ -static int datalockinit = 0; -static int spoollockinit = 0; +/* Our saved lock types. */ static enum locktype datalocktype, spoollocktype; - /* top of list containing all open locks */ static struct lock *l_top = NULL; @@ -96,7 +90,7 @@ static int lkopen_lockf (const char *, int, mode_t, int *); static int lkopen_flock (const char *, int, mode_t, int *); #endif /* HAVE_FLOCK */ -static enum locktype init_locktype(const char *); +static enum locktype init_locktype(const char *) PURE; static int lkopen_dot (const char *, int, mode_t, int *); static void lkclose_dot (int, const char *); @@ -117,17 +111,18 @@ static int lockit (struct lockinfo *); int lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock) { - if (! datalockinit) { - char *cp = context_find("datalocking"); + static bool deja_vu; + + if (!deja_vu) { + char *dl; - if (cp) { - datalocktype = init_locktype(cp); + deja_vu = true; + if ((dl = context_find("datalocking"))) { + datalocktype = init_locktype(dl); } else { /* We default to fcntl locking for data files */ datalocktype = FCNTL_LOCKING; } - - datalockinit = 1; } return lkopen(file, access, mode, datalocktype, failed_to_lock); @@ -140,10 +135,11 @@ lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock) int lkopenspool(const char *file, int access, mode_t mode, int *failed_to_lock) { - if (! spoollockinit) { - spoollocktype = init_locktype(spoollocking); + static bool deja_vu; - spoollockinit = 1; + if (!deja_vu) { + deja_vu = true; + spoollocktype = init_locktype(spoollocking); } return lkopen(file, access, mode, spoollocktype, failed_to_lock); @@ -276,20 +272,19 @@ str2accbits(const char *mode) { if (strcmp (mode, "r") == 0) return O_RDONLY; - else if (strcmp (mode, "r+") == 0) + if (strcmp (mode, "r+") == 0) return O_RDWR; - else if (strcmp (mode, "w") == 0) + if (strcmp (mode, "w") == 0) return O_WRONLY | O_CREAT | O_TRUNC; - else if (strcmp (mode, "w+") == 0) + if (strcmp (mode, "w+") == 0) return O_RDWR | O_CREAT | O_TRUNC; - else if (strcmp (mode, "a") == 0) + if (strcmp (mode, "a") == 0) return O_WRONLY | O_CREAT | O_APPEND; - else if (strcmp (mode, "a+") == 0) + if (strcmp (mode, "a+") == 0) return O_RDWR | O_CREAT | O_APPEND; - else { - errno = EINVAL; - return -1; - } + + errno = EINVAL; + return -1; } /* @@ -496,36 +491,38 @@ lkopen_dot (const char *file, int access, mode_t mode, int *failed_to_lock) { int i; for (i = 0; i < LOCK_RETRIES; ++i) { + struct stat st; + /* attempt to create lock file */ if (lockit (&lkinfo) == 0) { /* if successful, turn on timer and return */ timerON (lkinfo.curlock, fd); return fd; - } else { - /* - * Abort locking, if we fail to lock after 5 attempts - * and are never able to stat the lock file. Or, if - * we can stat the lockfile but exceed LOCK_RETRIES - * seconds waiting for it (by falling out of the loop). - */ - struct stat st; - if (stat (lkinfo.curlock, &st) == -1) { - if (i++ > 5) break; - sleep (1); - } else { - time_t curtime; - time (&curtime); - - /* check for stale lockfile, else sleep */ - if (curtime > st.st_ctime + RSECS) - (void) m_unlink (lkinfo.curlock); - else - sleep (1); - } - lockname (file, &lkinfo, 1); } + + /* + * Abort locking, if we fail to lock after 5 attempts + * and are never able to stat the lock file. Or, if + * we can stat the lockfile but exceed LOCK_RETRIES + * seconds waiting for it (by falling out of the loop). + */ + if (stat (lkinfo.curlock, &st) == -1) { + if (i++ > 5) break; + sleep (1); + } else { + time_t curtime; + time (&curtime); + + /* check for stale lockfile, else sleep */ + if (curtime > st.st_ctime + RSECS) + (void) m_unlink (lkinfo.curlock); + else + sleep (1); + } + lockname (file, &lkinfo, 1); } + close(fd); *failed_to_lock = 1; return -1; } @@ -534,11 +531,10 @@ lkopen_dot (const char *file, int access, mode_t mode, int *failed_to_lock) timerON(lkinfo.curlock, fd); return fd; } - else { - close(fd); - *failed_to_lock = 1; - return -1; - } + + close(fd); + *failed_to_lock = 1; + return -1; #endif /* HAVE_LIBLOCKFILE */ } @@ -561,7 +557,7 @@ lockit (struct lockinfo *li) curlock = li->curlock; if ((tmpfile = m_mktemp(li->tmplock, &fd, NULL)) == NULL) { - advise(NULL, "unable to create temporary file in %s", li->tmplock); + inform("unable to create temporary file in %s", li->tmplock); return -1; } @@ -580,7 +576,7 @@ lockit (struct lockinfo *li) fd = link(tmpfile, curlock); (void) m_unlink(tmpfile); - return (fd == -1 ? -1 : 0); + return fd == -1 ? -1 : 0; } #endif /* HAVE_LIBLOCKFILE */ @@ -633,7 +629,9 @@ lockname (const char *file, struct lockinfo *li, int isnewlock) snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp); -#if !defined(HAVE_LIBLOCKFILE) +#if defined(HAVE_LIBLOCKFILE) + NMH_UNUSED(isnewlock); +#else /* * If this is for a new lock, create a name for * the temporary lock file for lockit() @@ -658,14 +656,10 @@ static void timerON (char *curlock, int fd) { struct lock *lp; - size_t len; NEW(lp); - - len = strlen(curlock) + 1; + lp->l_lock = mh_xstrdup(curlock); lp->l_fd = fd; - lp->l_lock = mh_xmalloc (len); - memcpy (lp->l_lock, curlock, len); lp->l_next = l_top; if (!l_top) { @@ -673,7 +667,6 @@ timerON (char *curlock, int fd) SIGNAL (SIGALRM, alrmser); alarm (NSECS); } - l_top = lp; } @@ -752,23 +745,25 @@ init_locktype(const char *lockname) { if (strcasecmp(lockname, "fcntl") == 0) { return FCNTL_LOCKING; - } else if (strcasecmp(lockname, "lockf") == 0) { + } + if (strcasecmp(lockname, "lockf") == 0) { #ifdef HAVE_LOCKF return LOCKF_LOCKING; #else /* ! HAVE_LOCKF */ adios(NULL, "lockf not supported on this system"); #endif /* HAVE_LOCKF */ - } else if (strcasecmp(lockname, "flock") == 0) { + } + if (strcasecmp(lockname, "flock") == 0) { #ifdef HAVE_FLOCK return FLOCK_LOCKING; #else /* ! HAVE_FLOCK */ adios(NULL, "flock not supported on this system"); #endif /* HAVE_FLOCK */ - } else if (strcasecmp(lockname, "dot") == 0) { + } + if (strcasecmp(lockname, "dot") == 0) { return DOT_LOCKING; - } else { - adios(NULL, "Unknown lock type: \"%s\"", lockname); - /* NOTREACHED */ - return 0; } + adios(NULL, "Unknown lock type: \"%s\"", lockname); + /* NOTREACHED */ + return 0; }