summaryrefslogtreecommitdiffstats
path: root/mount/sundries.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount/sundries.c')
-rw-r--r--mount/sundries.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/mount/sundries.c b/mount/sundries.c
index 45e0e14d8..5ebf0195f 100644
--- a/mount/sundries.c
+++ b/mount/sundries.c
@@ -1,9 +1,12 @@
/*
* Support functions. Exported functions are prototyped in sundries.h.
* sundries.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ *
+ * added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
*/
#include "sundries.h"
+#include "mount.h"
/* File pointer for /etc/mtab. */
FILE *F_mtab = NULL;
@@ -14,6 +17,9 @@ FILE *F_temp = NULL;
/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
static int lock = -1;
+/* Flag for already existing lock file. */
+static int old_lockfile = 1;
+
/* String list constructor. (car() and cdr() are defined in "sundries.h"). */
string_list
cons (char *a, const string_list b)
@@ -75,6 +81,7 @@ error (const char *fmt, ...)
{
va_list args;
+ if (mount_quiet) return;
va_start (args, fmt);
vfprintf (stderr, fmt, args);
fprintf (stderr, "\n");
@@ -103,6 +110,12 @@ handler (int sig)
die (2, "%s", sys_siglist[sig]);
}
+static void
+setlkw_timeout (int sig)
+{
+ /* nothing, fcntl will fail anyway */
+}
+
/* Create the lock file. The lock file will be removed if we catch a signal
or when we exit. The value of lock is tested to remove the race. */
void
@@ -110,20 +123,54 @@ lock_mtab (void)
{
int sig = 0;
struct sigaction sa;
+ struct flock flock;
/* If this is the first time, ensure that the lock will be removed. */
if (lock < 0)
{
+ struct stat st;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigfillset (&sa.sa_mask);
while (sigismember (&sa.sa_mask, ++sig) != -1)
- sigaction (sig, &sa, (struct sigaction *) 0);
-
- if ((lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0)) < 0)
- die (2, "can't create lock file %s: %s",
- MOUNTED_LOCK, strerror (errno));
+ {
+ if (sig == SIGALRM)
+ sa.sa_handler = setlkw_timeout;
+ else
+ sa.sa_handler = handler;
+ sigaction (sig, &sa, (struct sigaction *) 0);
+ }
+
+ /* This stat is performed so we know when not to be overly eager
+ when cleaning up after signals. The window between stat and
+ open is not significant. */
+ if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT)
+ old_lockfile = 0;
+
+ lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0);
+ if (lock < 0)
+ {
+ die (2, "can't create lock file %s: %s",
+ MOUNTED_LOCK, strerror (errno));
+ }
+
+ flock.l_type = F_WRLCK;
+ flock.l_whence = SEEK_SET;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ alarm(LOCK_BUSY);
+ if (fcntl (lock, F_SETLKW, &flock) < 0)
+ {
+ close (lock);
+ /* The file should not be removed */
+ lock = -1;
+ die (2, "can't lock lock file %s: %s",
+ MOUNTED_LOCK, errno == EINTR ? "timed out" : strerror (errno));
+ }
+ /* We have now access to the lock, and it can always be removed */
+ old_lockfile = 0;
}
}
@@ -133,8 +180,9 @@ unlock_mtab (void)
{
if (lock != -1)
{
- close( lock );
- unlink (MOUNTED_LOCK);
+ close (lock);
+ if (!old_lockfile)
+ unlink (MOUNTED_LOCK);
}
}