From: David Levine Date: Sun, 6 Apr 2014 18:55:27 +0000 (-0500) Subject: Instead of relying on errno to determine if locking failed, pass X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/1c91be5784ddebaa6a54f1f2c42a8016f10af6de Instead of relying on errno to determine if locking failed, pass back explicit indication in int * argument to lk(f)opendata() and lkopenspool(). --- diff --git a/h/prototypes.h b/h/prototypes.h index 4f1d3295..0edcf411 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -178,16 +178,17 @@ int get_term_numcap(char *capability); * * Files opened for reading are locked with a read lock (if possible by * the underlying lock mechanism), files opened for writing are locked - * using an exclusive lock. + * using an exclusive lock. The int * argument is used to indicate failure + * to acquire a lock. */ int lkclosedata(int, const char *); int lkclosespool(int, const char *); int lkfclosedata(FILE *, const char *); int lkfclosespool(FILE *, const char *); -FILE *lkfopendata(const char *, const char *); -int lkopendata(const char *, int, mode_t); +FILE *lkfopendata(const char *, const char *, int *); +int lkopendata(const char *, int, mode_t, int *); FILE *lkfopenspool(const char *, const char *); -int lkopenspool(const char *, int, mode_t); +int lkopenspool(const char *, int, mode_t, int *); int m_atoi (char *); char *m_backup (char *); int m_convert (struct msgs *, char *); diff --git a/sbr/context_read.c b/sbr/context_read.c index 164f6794..8f63fedf 100644 --- a/sbr/context_read.c +++ b/sbr/context_read.c @@ -34,6 +34,7 @@ context_read (void) struct stat st; /* stat() results */ register struct passwd *pw; /* getpwuid() results */ register FILE *ib; /* profile and context file pointer */ + int failed_to_lock = 0; /* * If this routine _is_ called again (despite the wanings in the @@ -135,7 +136,7 @@ context_read (void) ctxpath = getcpy (m_maildir (cp)); - if ((ib = lkfopendata (ctxpath, "r"))) { + if ((ib = lkfopendata (ctxpath, "r", &failed_to_lock))) { readconfig ((struct node **) 0, ib, cp, 1); lkfclosedata (ib, ctxpath); } diff --git a/sbr/context_save.c b/sbr/context_save.c index 9105a596..70809595 100644 --- a/sbr/context_save.c +++ b/sbr/context_save.c @@ -23,6 +23,7 @@ context_save (void) register struct node *np; FILE *out; sigset_t set, oset; + int failed_to_lock = 0; /* No context in use -- silently ignore any changes! */ if (!ctxpath) @@ -43,8 +44,13 @@ context_save (void) sigaddset (&set, SIGTERM); sigprocmask (SIG_BLOCK, &set, &oset); - if (!(out = lkfopendata (ctxpath, "w"))) - adios (ctxpath, "unable to write"); + if (!(out = lkfopendata (ctxpath, "w", &failed_to_lock))) { + if (failed_to_lock) { + adios (ctxpath, "failed to lock"); + } else { + adios (ctxpath, "unable to write"); + } + } for (np = m_defs; np; np = np->n_next) if (np->n_context) fprintf (out, "%s: %s\n", np->n_name, np->n_field); diff --git a/sbr/lock_file.c b/sbr/lock_file.c index 3e322ba5..b8e47dfc 100644 --- a/sbr/lock_file.c +++ b/sbr/lock_file.c @@ -85,20 +85,20 @@ static enum locktype datalocktype, spoollocktype; /* top of list containing all open locks */ static struct lock *l_top = NULL; -static int lkopen(const char *, int, mode_t, enum locktype); +static int lkopen(const char *, int, mode_t, enum locktype, int *); static int str2accbits(const char *); -static int lkopen_fcntl (const char *, int, mode_t); +static int lkopen_fcntl (const char *, int, mode_t, int *); #ifdef HAVE_LOCKF -static int lkopen_lockf (const char *, int, mode_t); +static int lkopen_lockf (const char *, int, mode_t, int *); #endif /* HAVE_LOCKF */ #ifdef HAVE_FLOCK -static int lkopen_flock (const char *, int, mode_t); +static int lkopen_flock (const char *, int, mode_t, int *); #endif /* HAVE_FLOCK */ static enum locktype init_locktype(const char *); -static int lkopen_dot (const char *, int, mode_t); +static int lkopen_dot (const char *, int, mode_t, int *); static void lkclose_dot (int, const char *); static void lockname (const char *, struct lockinfo *, int); static void timerON (char *, int); @@ -115,7 +115,7 @@ static int lockit (struct lockinfo *); */ int -lkopendata(const char *file, int access, mode_t mode) +lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock) { if (! datalockinit) { char *cp = context_find("datalocking"); @@ -130,7 +130,7 @@ lkopendata(const char *file, int access, mode_t mode) datalockinit = 1; } - return lkopen(file, access, mode, datalocktype); + return lkopen(file, access, mode, datalocktype, failed_to_lock); } @@ -138,7 +138,7 @@ lkopendata(const char *file, int access, mode_t mode) * Locking using the spool locking algorithm */ -int lkopenspool(const char *file, int access, mode_t mode) +int lkopenspool(const char *file, int access, mode_t mode, int *failed_to_lock) { if (! spoollockinit) { spoollocktype = init_locktype(spoollocking); @@ -146,7 +146,7 @@ int lkopenspool(const char *file, int access, mode_t mode) spoollockinit = 1; } - return lkopen(file, access, mode, spoollocktype); + return lkopen(file, access, mode, spoollocktype, failed_to_lock); } @@ -155,7 +155,7 @@ int lkopenspool(const char *file, int access, mode_t mode) */ FILE * -lkfopendata(const char *file, const char *mode) +lkfopendata(const char *file, const char *mode, int *failed_to_lock) { FILE *fp; int oflags = str2accbits(mode); @@ -166,7 +166,7 @@ lkfopendata(const char *file, const char *mode) return NULL; } - if ((fd = lkopendata(file, oflags, 0666)) == -1) + if ((fd = lkopendata(file, oflags, 0666, failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { @@ -182,6 +182,7 @@ lkfopenspool(const char *file, const char *mode) { FILE *fp; int oflags = str2accbits(mode); + int failed_to_lock = 0; int fd; if (oflags == -1) { @@ -189,7 +190,7 @@ lkfopenspool(const char *file, const char *mode) return NULL; } - if ((fd = lkopenspool(file, oflags, 0666)) == -1) + if ((fd = lkopenspool(file, oflags, 0666, &failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { @@ -296,24 +297,25 @@ str2accbits(const char *mode) */ static int -lkopen (const char *file, int access, mode_t mode, enum locktype ltype) +lkopen (const char *file, int access, mode_t mode, enum locktype ltype, + int *failed_to_lock) { switch (ltype) { case FCNTL_LOCKING: - return lkopen_fcntl(file, access, mode); + return lkopen_fcntl(file, access, mode, failed_to_lock); case DOT_LOCKING: - return lkopen_dot(file, access, mode); + return lkopen_dot(file, access, mode, failed_to_lock); #ifdef HAVE_FLOCK case FLOCK_LOCKING: - return lkopen_flock(file, access, mode); + return lkopen_flock(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ #ifdef HAVE_LOCKF case LOCKF_LOCKING: - return lkopen_lockf(file, access, mode); + return lkopen_lockf(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ default: @@ -348,7 +350,7 @@ lkclose_dot (int fd, const char *file) */ static int -lkopen_fcntl(const char *file, int access, mode_t mode) +lkopen_fcntl(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno; struct flock flk; @@ -375,6 +377,7 @@ lkopen_fcntl(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } @@ -386,7 +389,7 @@ lkopen_fcntl(const char *file, int access, mode_t mode) */ static int -lkopen_flock(const char *file, int access, mode_t mode) +lkopen_flock(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, locktype; @@ -410,6 +413,7 @@ lkopen_flock(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } @@ -420,7 +424,7 @@ lkopen_flock(const char *file, int access, mode_t mode) */ static int -lkopen_lockf(const char *file, int access, mode_t mode) +lkopen_lockf(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, saved_access; @@ -462,6 +466,7 @@ lkopen_lockf(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } @@ -472,7 +477,7 @@ lkopen_lockf(const char *file, int access, mode_t mode) */ static int -lkopen_dot (const char *file, int access, mode_t mode) +lkopen_dot (const char *file, int access, mode_t mode, int *failed_to_lock) { int fd; struct lockinfo lkinfo; @@ -503,8 +508,10 @@ lkopen_dot (const char *file, int access, mode_t mode) */ struct stat st; if (stat (lkinfo.curlock, &st) == -1) { - if (i++ > 5) + if (i++ > 5) { + *failed_to_lock = 1; return -1; + } sleep (5); } else { time_t curtime; @@ -528,6 +535,7 @@ lkopen_dot (const char *file, int access, mode_t mode) } else { close(fd); + *failed_to_lock = 1; return -1; } #endif /* HAVE_LIBLOCKFILE */ diff --git a/sbr/seq_read.c b/sbr/seq_read.c index 44e25799..9b071a4e 100644 --- a/sbr/seq_read.c +++ b/sbr/seq_read.c @@ -15,7 +15,7 @@ * static prototypes */ static int seq_init (struct msgs *, char *, char *); -static int seq_public (struct msgs *, int); +static int seq_public (struct msgs *, int, int *); static void seq_private (struct msgs *); @@ -28,6 +28,8 @@ static void seq_private (struct msgs *); int seq_read (struct msgs *mp, int lockflag) { + int failed_to_lock = 0; + /* * Initialize the list of sequence names. Go ahead and * add the "cur" sequence to the list of sequences. @@ -40,11 +42,8 @@ seq_read (struct msgs *mp, int lockflag) return OK; /* Initialize the public sequences */ - if (seq_public (mp, lockflag) == NOTOK) { - if (errno == EACCES || errno == EAGAIN || errno == EWOULDBLOCK) { - /* Failed to lock sequence file. */ - return NOTOK; - } + if (seq_public (mp, lockflag, &failed_to_lock) == NOTOK) { + if (failed_to_lock) return NOTOK; } /* Initialize the private sequences */ @@ -59,7 +58,7 @@ seq_read (struct msgs *mp, int lockflag) */ static int -seq_public (struct msgs *mp, int lockflag) +seq_public (struct msgs *mp, int lockflag, int *failed_to_lock) { int state; char *cp, seqfile[PATH_MAX]; @@ -78,7 +77,8 @@ seq_public (struct msgs *mp, int lockflag) /* get filename of sequence file */ snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq); - if ((fp = lkfopendata (seqfile, lockflag ? "r+" : "r")) == NULL) + if ((fp = lkfopendata (seqfile, lockflag ? "r+" : "r", failed_to_lock)) + == NULL) return NOTOK; /* Use m_getfld to scan sequence file */ diff --git a/sbr/seq_save.c b/sbr/seq_save.c index 5b06dcdf..5148f745 100644 --- a/sbr/seq_save.c +++ b/sbr/seq_save.c @@ -77,6 +77,8 @@ priv: context_del (attr); /* delete sequence from context */ if (!fp) { + int failed_to_lock = 0; + /* * Attempt to open file for public sequences. * If that fails (probably because folder is @@ -90,10 +92,16 @@ priv: mp->seqname = NULL; rewind(fp); ftruncate(fileno(fp), 0); - } else if ((fp = lkfopendata (seqfile, "w")) == NULL + } else if ((fp = lkfopendata (seqfile, "w", &failed_to_lock)) + == NULL && (m_unlink (seqfile) == -1 || - (fp = lkfopendata (seqfile, "w")) == NULL)) { - admonish (attr, "unable to write"); + (fp = lkfopendata (seqfile, "w", &failed_to_lock)) + == NULL)) { + if (failed_to_lock) { + admonish (attr, "unable to lock"); + } else { + admonish (attr, "unable to write"); + } goto priv; } diff --git a/uip/annosbr.c b/uip/annosbr.c index 88c90f44..a73c8277 100644 --- a/uip/annosbr.c +++ b/uip/annosbr.c @@ -32,15 +32,20 @@ annotate (char *file, char *comp, char *text, int inplace, int datesw, int delet int i, fd; struct utimbuf b; struct stat s; + int failed_to_lock = 0; /* open and lock the file to be annotated */ - if ((fd = lkopendata (file, O_RDWR, 0)) == NOTOK) { + if ((fd = lkopendata (file, O_RDWR, 0, &failed_to_lock)) == NOTOK) { switch (errno) { case ENOENT: break; default: - admonish (file, "unable to lock and open"); + if (failed_to_lock) { + admonish (file, "unable to lock"); + } else { + admonish (file, "unable to open"); + } break; } return 1; diff --git a/uip/dropsbr.c b/uip/dropsbr.c index da2752d1..915e71e6 100644 --- a/uip/dropsbr.c +++ b/uip/dropsbr.c @@ -47,26 +47,16 @@ mbx_open (char *file, int mbx_style, uid_t uid, gid_t gid, mode_t mode) /* attempt to open and lock file */ for (count = 4; count > 0; count--) { + int failed_to_lock = 0; if ((fd = lkopenspool (file, O_RDWR | O_CREAT | - O_NONBLOCK, mode)) == NOTOK) { - switch (errno) { -#if defined(FCNTL_LOCKING) || defined(LOCKF_LOCKING) - case EACCES: - case EAGAIN: -#endif - -#ifdef FLOCK_LOCKING - case EWOULDBLOCK: -#endif - case ETXTBSY: - j = errno; - sleep (5); - continue; - - default: - /* just return error */ - return NOTOK; - } + O_NONBLOCK, mode, &failed_to_lock)) == NOTOK) { + if (failed_to_lock) { + j = errno; + sleep (5); + continue; + } else { + return NOTOK; + } } /* good file descriptor */ diff --git a/uip/mhcachesbr.c b/uip/mhcachesbr.c index 7e684e1f..7814d6ee 100644 --- a/uip/mhcachesbr.c +++ b/uip/mhcachesbr.c @@ -279,6 +279,7 @@ find_cache_aux (int writing, char *directory, char *id, int mask, usemap; char mapfile[BUFSIZ], mapname[BUFSIZ]; FILE *fp; + int failed_to_lock = 0; static int partno, pid; static time_t clock = 0; @@ -333,12 +334,15 @@ use_raw: make_intermediates (mapfile); mask = umask (writing == 2 ? 0077 : 0); - if (!(fp = lkfopendata (mapfile, "a")) && errno == ENOENT) { + if (!(fp = lkfopendata (mapfile, "a", &failed_to_lock)) && errno == ENOENT) { int fd; if ((fd = creat (mapfile, 0666)) != NOTOK) { close (fd); - fp = lkfopendata (mapfile, "a"); + fp = lkfopendata (mapfile, "a", &failed_to_lock); + if (failed_to_lock) { + adios (mapfile, "failed to lock"); + } } } umask (mask); @@ -366,8 +370,9 @@ find_cache_aux2 (char *mapfile, char *id, char *mapname, int namelen) char buf[BUFSIZ], name[NAMESZ]; FILE *fp; m_getfld_state_t gstate = 0; + int failed_to_lock = 0; - if (!(fp = lkfopendata (mapfile, "r"))) + if (!(fp = lkfopendata (mapfile, "r", &failed_to_lock))) return NOTOK; for (;;) { diff --git a/uip/msh.c b/uip/msh.c index e91924c3..86855a4f 100644 --- a/uip/msh.c +++ b/uip/msh.c @@ -1079,6 +1079,7 @@ quit (void) char map1[BUFSIZ], map2[BUFSIZ]; struct stat st; FILE *dp; + int failed_to_lock = 0; if (!(mp->msgflags & MODIFIED) || is_readonly(mp) || fmsh) { if (vmh) @@ -1089,7 +1090,7 @@ quit (void) if (vmh) ttyNaux (NULLCMD, "FAST"); cp = NULL; - if ((dp = lkfopendata (mp->foldpath, "r")) == NULL) { + if ((dp = lkfopendata (mp->foldpath, "r", &failed_to_lock)) == NULL) { advise (mp->foldpath, "unable to lock"); if (vmh) { ttyR (NULLCMD); diff --git a/uip/new.c b/uip/new.c index a0683dd2..8d235b17 100644 --- a/uip/new.c +++ b/uip/new.c @@ -95,6 +95,7 @@ get_msgnums(char *folder, char *sequences[]) char name[NAMESZ], field[BUFSIZ]; char *cp; char *msgnums = NULL, *this_msgnums, *old_msgnums; + int failed_to_lock = 0; m_getfld_state_t gstate = 0; /* copied from seq_read.c:seq_public */ @@ -112,11 +113,10 @@ get_msgnums(char *folder, char *sequences[]) if (seqfile == NULL) return NULL; - if ((fp = lkfopendata (seqfile, "r")) == NULL) { + if ((fp = lkfopendata (seqfile, "r", & failed_to_lock)) == NULL) { free(seqfile); - if (errno == EACCES || errno == EAGAIN || errno == EWOULDBLOCK) { - /* Failed to lock sequence file. */ + if (failed_to_lock) { adios (seqfile, "failed to lock"); } else { return NULL; diff --git a/uip/slocal.c b/uip/slocal.c index fb21c880..ff3cabf8 100644 --- a/uip/slocal.c +++ b/uip/slocal.c @@ -1414,6 +1414,7 @@ suppress_duplicates (int fd, char *file) rewind (in); for (;;) { + int failed_to_lock = 0; int bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); switch (state) { @@ -1451,7 +1452,8 @@ suppress_duplicates (int fd, char *file) * This will fail if your Maildelivery file doesn't * exist. */ - if ((lockfd = lkopendata(file, O_RDWR, 0)) == -1) { + if ((lockfd = lkopendata(file, O_RDWR, 0, &failed_to_lock)) + == -1) { advise (file, "unable to perform file locking on"); free (cp); fclose (in);