summaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libunix/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/libexec/uucp/libunix/lock.c')
-rw-r--r--gnu/libexec/uucp/libunix/lock.c279
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 */