X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=sbr%2Flock_file.c;h=866d047774cbd5d0540a8ef0f1f27cd9a6b3e971;hp=fe42196bb2cfc13d4f693e293bdf9a946f41b562;hb=07f336c16bdb2316c0e32debb3c7ed2e5a89e49a;hpb=045b9601403a216c400642229f2b291f85f88f7d diff --git a/sbr/lock_file.c b/sbr/lock_file.c index fe42196..866d047 100644 --- a/sbr/lock_file.c +++ b/sbr/lock_file.c @@ -3,20 +3,39 @@ * 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 Sun, 28 Mar 1999 15:34:03 +0200 + */ + #include #include +#include + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef TM_IN_SYS_TIME +# include +# else +# include +# endif +#endif #ifdef HAVE_ERRNO_H # include #endif -#ifdef MMDFONLY -# include -# include -#endif /* MMDFONLY */ - #ifdef HAVE_FCNTL_H # include #else @@ -29,7 +48,9 @@ #include -extern int errno; +#if defined(HAVE_LIBLOCKFILE) +#include +#endif #ifdef LOCKDIR char *lockdir = LOCKDIR; @@ -45,7 +66,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 +77,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 { @@ -80,13 +105,15 @@ static int lkopen_kernel (char *, int, mode_t); #ifdef DOT_LOCKING static int lkopen_dot (char *, int, mode_t); -static int lockit (struct lockinfo *); static void lockname (char *, struct lockinfo *, int); static void timerON (char *, int); static void timerOFF (int); static RETSIGTYPE alrmser (int); #endif +#if !defined(HAVE_LIBLOCKFILE) +static int lockit (struct lockinfo *); +#endif /* * Base routine to open and lock a file, @@ -145,9 +172,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 +197,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 +263,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 +322,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 @@ -310,10 +358,8 @@ lkopen_kernel (char *file, int access, mode_t mode) static int lkopen_dot (char *file, int access, mode_t mode) { - int i, fd; - time_t curtime; + int fd; struct lockinfo lkinfo; - struct stat st; /* open the file */ if ((fd = open (file, access, mode)) == -1) @@ -325,35 +371,53 @@ lkopen_dot (char *file, int access, mode_t mode) */ lockname (file, &lkinfo, 1); - for (i = 0;;) { - /* 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. - */ - if (stat (lkinfo.curlock, &st) == -1) { - if (i++ > 5) - return -1; - sleep (5); +#if !defined(HAVE_LIBLOCKFILE) + { + int i; + for (i = 0;;) { + /* attempt to create lock file */ + if (lockit (&lkinfo) == 0) { + /* if successful, turn on timer and return */ + timerON (lkinfo.curlock, fd); + return fd; } else { - i = 0; - time (&curtime); - - /* check for stale lockfile, else sleep */ - if (curtime > st.st_ctime + RSECS) - unlink (lkinfo.curlock); - else + /* + * Abort locking, if we fail to lock after 5 attempts + * and are never able to stat the lock file. + */ + struct stat st; + if (stat (lkinfo.curlock, &st) == -1) { + if (i++ > 5) + return -1; sleep (5); + } else { + time_t curtime; + i = 0; + time (&curtime); + + /* check for stale lockfile, else sleep */ + if (curtime > st.st_ctime + RSECS) + unlink (lkinfo.curlock); + else + sleep (5); + } + lockname (file, &lkinfo, 1); } } } +#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 +436,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 +466,7 @@ lockit (struct lockinfo *li) return (fd == -1 ? -1 : 0); } +#endif /* HAVE_LIBLOCKFILE */ /* * Get name of lock file, and temporary lock file @@ -420,7 +494,7 @@ lockname (char *file, struct lockinfo *li, int isnewlock) bplen += tmplen; #else if (cp != file) { - snprintf (bp, sizeof(li->curlock), "%.*s", cp - file, file); + snprintf (bp, sizeof(li->curlock), "%.*s", (int)(cp - file), file); tmplen = strlen (bp); bp += tmplen; bplen += tmplen; @@ -442,6 +516,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() @@ -451,20 +526,9 @@ lockname (char *file, struct lockinfo *li, int isnewlock) strncpy (li->tmplock, ",LCK.XXXXXX", sizeof(li->tmplock)); else snprintf (li->tmplock, sizeof(li->tmplock), "%.*s,LCK.XXXXXX", - cp - li->curlock, li->curlock); -/* - Mkstemp work postponed until later -Doug -#ifdef HAVE_MKSTEMP - mkstemp (li->tmplock); -#else -*/ - mktemp (li->tmplock); -/* -#endif -*/ - - unlink (li->tmplock); /* remove any stray */ + (int)(cp - li->curlock), li->curlock); } +#endif } @@ -479,15 +543,11 @@ timerON (char *curlock, int fd) struct lock *lp; size_t len; - if (!(lp = (struct lock *) malloc (sizeof(*lp)))) - return; + lp = (struct lock *) mh_xmalloc (sizeof(*lp)); len = strlen(curlock) + 1; lp->l_fd = fd; - if (!(lp->l_lock = malloc (len))) { - free ((char *) lp); - return; - } + lp->l_lock = mh_xmalloc (len); memcpy (lp->l_lock, curlock, len); lp->l_next = l_top; @@ -543,7 +603,6 @@ timerOFF (int fd) static RETSIGTYPE alrmser (int sig) { - int j; char *lockfile; struct lock *lp; @@ -554,8 +613,15 @@ 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 (*lockfile && (j = creat (lockfile, 0600)) != -1) - close (j); +#if !defined(HAVE_LIBLOCKFILE) + { + int j; + if (*lockfile && (j = creat (lockfile, 0600)) != -1) + close (j); + } +#else + lockfile_touch(lockfile); +#endif } /* restart the alarm */