diff options
Diffstat (limited to 'gnu/libexec/uucp/libunix/lock.c')
-rw-r--r-- | gnu/libexec/uucp/libunix/lock.c | 279 |
1 files changed, 233 insertions, 46 deletions
diff --git a/gnu/libexec/uucp/libunix/lock.c b/gnu/libexec/uucp/libunix/lock.c index d823213017b6..4011534291d7 100644 --- a/gnu/libexec/uucp/libunix/lock.c +++ b/gnu/libexec/uucp/libunix/lock.c @@ -1,7 +1,7 @@ /* lock.c Lock and unlock a file name. - Copyright (C) 1991, 1992 Ian Lance Taylor + Copyright (C) 1991, 1992, 1993 Ian Lance Taylor This file is part of the Taylor UUCP package. @@ -20,13 +20,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author of the program may be contacted at ian@airs.com or - c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139. */ #include "uucp.h" #if USE_RCS_ID -const char lock_rcsid[] = "$Id: lock.c,v 1.1 1993/08/05 18:24:06 conklin Exp $"; +const char lock_rcsid[] = "$Id: lock.c,v 1.2 1994/05/07 18:10:40 ache Exp $"; #endif #include "uudefs.h" @@ -43,6 +43,19 @@ const char lock_rcsid[] = "$Id: lock.c,v 1.1 1993/08/05 18:24:06 conklin Exp $"; #endif #endif +#if TM_IN_SYS_TIME +#include <sys/time.h> +#else +#include <time.h> +#endif + +#if HAVE_QNX_LOCKFILES +#include <sys/kernel.h> +#include <sys/psinfo.h> +#include <sys/seginfo.h> +#include <sys/vc.h> +#endif + #ifndef O_RDONLY #define O_RDONLY 0 #define O_WRONLY 1 @@ -56,6 +69,15 @@ const char lock_rcsid[] = "$Id: lock.c,v 1.1 1993/08/05 18:24:06 conklin Exp $"; #ifndef SEEK_SET #define SEEK_SET 0 #endif + +#ifndef localtime +extern struct tm *localtime (); +#endif + +#if HAVE_QNX_LOCKFILES +static boolean fsqnx_stale P((unsigned long ipid, unsigned long inme, + unsigned long inid, boolean *pferr)); +#endif /* Lock something. If the fspooldir argument is TRUE, the argument is a file name relative to the spool directory; otherwise the argument @@ -73,13 +95,19 @@ fsdo_lock (zlock, fspooldir, pferr) size_t cslash; pid_t ime; char *ztempfile; - char abtempfile[sizeof "TMP1234567890"]; + char abtempfile[sizeof "TMP12345678901234567890"]; int o; +#if HAVE_QNX_LOCKFILES + nid_t inme; + char ab[23]; + char *zend; +#else #if HAVE_V2_LOCKFILES int i; #else char ab[12]; #endif +#endif int cwrote; const char *zerr; boolean fret; @@ -99,6 +127,9 @@ fsdo_lock (zlock, fspooldir, pferr) } ime = getpid (); +#if HAVE_QNX_LOCKFILES + inme = getnid (); +#endif /* We do the actual lock by creating a file and then linking it to the final file name we want. This avoids race conditions due to @@ -114,7 +145,12 @@ fsdo_lock (zlock, fspooldir, pferr) else cslash = zslash - zpath + 1; +#if HAVE_QNX_LOCKFILES + sprintf (abtempfile, "TMP%010lx%010lx", (unsigned long) ime, + (unsigned long) inme); +#else sprintf (abtempfile, "TMP%010lx", (unsigned long) ime); +#endif ztempfile = zbufalc (cslash + sizeof abtempfile); memcpy (ztempfile, zpath, cslash); memcpy (ztempfile + cslash, abtempfile, sizeof abtempfile); @@ -141,13 +177,18 @@ fsdo_lock (zlock, fspooldir, pferr) } } +#if HAVE_QNX_LOCKFILES + sprintf (ab, "%10ld %10ld\n", (long) ime, (long) inid); + cwrote = write (o, ab, strlen (ab)); +#else #if HAVE_V2_LOCKFILES - i = ime; + i = (int) ime; cwrote = write (o, &i, sizeof i); #else - sprintf (ab, "%10d\n", (int) ime); + sprintf (ab, "%10ld\n", (long) ime); cwrote = write (o, ab, strlen (ab)); #endif +#endif zerr = NULL; if (cwrote < 0) @@ -177,8 +218,13 @@ fsdo_lock (zlock, fspooldir, pferr) while (link (ztempfile, zpath) != 0) { int cgot; - int ipid; + pid_t ipid; boolean freadonly; + struct stat st; + char abtime[sizeof "1991-12-31 12:00:00"]; +#if HAVE_QNX_LOCKFILES + nid_t inid; +#endif fret = FALSE; @@ -228,11 +274,17 @@ fsdo_lock (zlock, fspooldir, pferr) break; } +#if HAVE_QNX_LOCKFILES + ab[cgot] = '\0'; + ipid = (pid_t) strtol (ab, &zend, 10); + inid = (nid_t) strtol (zend, (char **) NULL, 10); +#else #if HAVE_V2_LOCKFILES - ipid = i; + ipid = (pid_t) i; #else ab[cgot] = '\0'; - ipid = strtol (ab, (char **) NULL, 10); + ipid = (pid_t) strtol (ab, (char **) NULL, 10); +#endif #endif /* On NFS, the link might have actually succeeded even though we @@ -247,18 +299,49 @@ fsdo_lock (zlock, fspooldir, pferr) going to worry about this possibility. */ if (ipid == ime) { - fret = TRUE; - break; +#if HAVE_QNX_LOCKFILES + if (inid == inme) +#endif + { + fret = TRUE; + break; + } } +#if HAVE_QNX_LOCKFILES + if (! fsqnx_stale ((unsigned long) ipid, (unsigned long) inme, + (unsigned long) inid, pferr)) + break; +#else /* If the process still exists, we will get EPERM rather than ESRCH. We then return FALSE to indicate that we cannot make the lock. */ if (kill (ipid, 0) == 0 || errno == EPERM) break; +#endif - ulog (LOG_ERROR, "Found stale lock %s held by process %d", - zpath, ipid); + if (fstat (o, &st) < 0) + strcpy (abtime, "unknown"); + else + { + time_t itm; + struct tm *q; + + itm = (time_t) st.st_mtime; + q = localtime (&itm); + sprintf (abtime, "%04d-%02d-%02d %02d:%02d:%02d", + q->tm_year + 1900, q->tm_mon + 1, q->tm_mday, q->tm_hour, + q->tm_min, q->tm_sec); + } + +#if HAVE_QNX_LOCKFILES + ulog (LOG_ERROR, + "Stale lock %s held by process %ld on node %ld created %s", + zpath, (long) ipid, (long) inid, abtime); +#else + ulog (LOG_ERROR, "Stale lock %s held by process %ld created %s", + zpath, (long) ipid, abtime); +#endif /* This is a stale lock, created by a process that no longer exists. @@ -317,6 +400,7 @@ fsdo_lock (zlock, fspooldir, pferr) (void) close (o); o = -1; (void) remove (zpath); + fret = TRUE; continue; } @@ -326,13 +410,18 @@ fsdo_lock (zlock, fspooldir, pferr) break; } +#if HAVE_QNX_LOCKFILES + sprintf (ab, "%10ld %10ld\n", (long) ime, (long) inid); + cwrote = write (o, ab, strlen (ab)); +#else #if HAVE_V2_LOCKFILES - i = ime; + i = (int) ime; cwrote = write (o, &i, sizeof i); #else - sprintf (ab, "%10d\n", (int) ime); + sprintf (ab, "%10ld\n", (long) ime); cwrote = write (o, ab, strlen (ab)); #endif +#endif if (cwrote < 0) { @@ -360,52 +449,63 @@ fsdo_lock (zlock, fspooldir, pferr) break; } +#if HAVE_QNX_LOCKFILES + ab[cgot] = '\0'; + ipid = (pid_t) strtol (ab, &zend, 10); + inid = (nid_t) strtol (zend, (char **) NULL, 10); +#else #if HAVE_V2_LOCKFILES - ipid = i; + ipid = (pid_t) i; #else ab[cgot] = '\0'; - ipid = strtol (ab, (char **) NULL, 10); + ipid = (pid_t) strtol (ab, (char **) NULL, 10); +#endif #endif if (ipid == ime) { - struct stat sfile, sdescriptor; - - /* It looks like we have the lock. Do the final stat - check. */ - if (stat ((char *) zpath, &sfile) < 0) - { - if (errno != ENOENT) - { - zerr = "stat"; - break; - } - /* Loop around and try again. */ - } - else +#if HAVE_QNX_LOCKFILES + if (inid == inme) +#endif { - if (fstat (o, &sdescriptor) < 0) + struct stat sfile, sdescriptor; + + /* It looks like we have the lock. Do the final stat + check. */ + if (stat ((char *) zpath, &sfile) < 0) { - zerr = "fstat"; - break; + if (errno != ENOENT) + { + zerr = "stat"; + break; + } + /* Loop around and try again. */ } - - if (sfile.st_ino == sdescriptor.st_ino - && sfile.st_dev == sdescriptor.st_dev) + else { - /* Close the file before assuming we've succeeded to - pick up any trailing errors. */ - if (close (o) < 0) + if (fstat (o, &sdescriptor) < 0) { - zerr = "close"; + zerr = "fstat"; break; } - o = -1; - - /* We have the lock. */ - fret = TRUE; - break; + if (sfile.st_ino == sdescriptor.st_ino + && sfile.st_dev == sdescriptor.st_dev) + { + /* Close the file before assuming we've + succeeded to pick up any trailing errors. */ + if (close (o) < 0) + { + zerr = "close"; + break; + } + + o = -1; + + /* We have the lock. */ + fret = TRUE; + break; + } } } } @@ -475,3 +575,90 @@ fsdo_unlock (zlock, fspooldir) return FALSE; } } + +#if HAVE_QNX_LOCKFILES + +/* Return TRUE if the lock is stale. */ + +static boolean +fsqnx_stale (ipid, inme, inid, pferr) + unsigned long ipid; + unsigned long inme; + unsigned long inid; + boolean *pferr; +{ + /* A virtual process ID. This virtual process ID, which will exist + on the local node, will represent the process ID of the process + manager process (Proc) on the remote node. */ + pid_t ivid; + /* The return value of the qnx_psinfo function. This is either a + process ID which might or might not be the same as the process + being looked for, or -1 to indicate no process found. */ + pid_t ifound_pid; + /* This holds the actual result of qnx_psinfo. We will ignore + almost all the fields since we're just checking for existence. */ + struct _psinfo spsdata; + + /* Establish connection with a remote process manager if necessary. */ + if (inid != inme) + { + ivid = qnx_vc_attach (inid /* remote node ID */, + PROC_PID /* pid of process manager */, + 1000 /* initial buffer size */, + 0 /* flags */); + if (ivid < 0) + { + ulog (LOG_ERROR, "qnx_vc_attach (%lu, PROC_PID): %s", + inid, strerror (errno)); + if (pferr != NULL) + *pferr = TRUE; + return FALSE; + } + } + else + { + /* Use the local pid of the local process manager. */ + ivid = PROC_PID; + } + + /* Request the process information. */ + ifound_pid = qnx_psinfo (ivid /* process manager handling request */, + ipid /* get info on this process */, + &spsdata /* put info in this struct */, + 0 /* unused */, + (struct _seginfo *) NULL /* unused */); + + /* Deallocate the virtual connection before continuing. */ + { + int isaved_errno = errno; + if (qnx_vc_detach (ivid) < 0) + ulog (LOG_ERROR, "qnx_vd_detach (%ld): %s", (long) ivid, + strerror (errno)); + errno = isaved_errno; + } + + /* If the returned pid matches then the process still holds the lock. */ + if ((ifound_pid == ipid) && (spsdata.pid == ipid)) + return FALSE; + + /* If the returned pid is positive and doesn't match, then the + process doesn't exist and the lock is stale. Continue. */ + + /* If the returned pid is negative (-1) and errno is EINVAL (or ESRCH + in older versions of QNX), then the process doesn't exist and the + lock is stale. Continue. */ + + /* Check for impossible errors. */ + if ((ifound_pid < 0) && (errno != ESRCH) && (errno != EINVAL)) + { + ulog (LOG_ERROR, "qnx_psinfo (%ld, %ld): %s", (long) ivid, + (long) ipid, strerror (errno)); + /* Since we don't know what the hell this means, and we don't + want our system to freeze, we treat this case as a stale + lock. Continue on. */ + } + + return TRUE; +} + +#endif /* HAVE_QNX_LOCKFILES */ |