summaryrefslogtreecommitdiffstats
path: root/mount/sundries.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount/sundries.c')
-rw-r--r--mount/sundries.c410
1 files changed, 153 insertions, 257 deletions
diff --git a/mount/sundries.c b/mount/sundries.c
index 5ebf0195f..4506924aa 100644
--- a/mount/sundries.c
+++ b/mount/sundries.c
@@ -4,328 +4,224 @@
*
* added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
*/
-
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h> /* for MNTTYPE_SWAP */
+#include "fstab.h"
#include "sundries.h"
-#include "mount.h"
-
-/* File pointer for /etc/mtab. */
-FILE *F_mtab = NULL;
-
-/* File pointer for temp mtab. */
-FILE *F_temp = NULL;
+#include "nfsmount.h"
-/* 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)
-{
- string_list p;
-
- p = xmalloc (sizeof *p);
+cons (char *a, const string_list b) {
+ string_list p;
- car (p) = a;
- cdr (p) = b;
- return p;
+ p = xmalloc (sizeof *p);
+ car (p) = a;
+ cdr (p) = b;
+ return p;
}
void *
-xmalloc (size_t size)
-{
- void *t;
+xmalloc (size_t size) {
+ void *t;
- if (size == 0)
- return NULL;
+ if (size == 0)
+ return NULL;
- t = malloc (size);
- if (t == NULL)
- die (2, "not enough memory");
+ t = malloc (size);
+ if (t == NULL)
+ die (EX_SYSERR, "not enough memory");
- return t;
+ return t;
}
char *
-xstrdup (const char *s)
-{
- char *t;
+xstrdup (const char *s) {
+ char *t;
- if (s == NULL)
- return NULL;
+ if (s == NULL)
+ return NULL;
- t = strdup (s);
+ t = strdup (s);
- if (t == NULL)
- die (2, "not enough memory");
+ if (t == NULL)
+ die (EX_SYSERR, "not enough memory");
- return t;
+ return t;
}
-/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
-void
-block_signals (int how)
-{
- sigset_t sigs;
+char *
+xstrndup (const char *s, int n) {
+ char *t;
- sigfillset (&sigs);
- sigprocmask (how, &sigs, (sigset_t *) 0);
-}
+ if (s == NULL)
+ die (EX_SOFTWARE, "bug in xstrndup call");
+ t = xmalloc(n+1);
+ strncpy(t,s,n);
+ t[n] = 0;
-/* Non-fatal error. Print message and return. */
-void
-error (const char *fmt, ...)
-{
- va_list args;
-
- if (mount_quiet) return;
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
+ return t;
}
-/* Fatal error. Print message and exit. */
-void
-die (int err, const char *fmt, ...)
-{
- va_list args;
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
+char *
+xstrconcat2 (const char *s, const char *t) {
+ char *res;
- unlock_mtab ();
- exit (err);
+ if (!s) s = "";
+ if (!t) t = "";
+ res = xmalloc(strlen(s) + strlen(t) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ return res;
}
-/* Ensure that the lock is released if we are interrupted. */
-static void
-handler (int sig)
-{
- die (2, "%s", sys_siglist[sig]);
-}
+char *
+xstrconcat3 (const char *s, const char *t, const char *u) {
+ char *res;
-static void
-setlkw_timeout (int sig)
-{
- /* nothing, fcntl will fail anyway */
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ return res;
}
-/* 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
-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)
- {
- 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;
- }
-}
+char *
+xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
+ char *res;
-/* Remove lock file. */
-void
-unlock_mtab (void)
-{
- if (lock != -1)
- {
- close (lock);
- if (!old_lockfile)
- unlink (MOUNTED_LOCK);
- }
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ if (!v) v = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + strlen(v) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ strcat(res, v);
+ return res;
}
-/* Open mtab. */
+/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
void
-open_mtab (const char *mode)
-{
- if ((F_mtab = setmntent (MOUNTED, mode)) == NULL)
- die (2, "can't open %s: %s", MOUNTED, strerror (errno));
-}
+block_signals (int how) {
+ sigset_t sigs;
-/* Close mtab. */
-void
-close_mtab (void)
-{
- if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
- endmntent (F_mtab);
+ sigfillset (&sigs);
+ sigdelset(&sigs, SIGTRAP);
+ sigdelset(&sigs, SIGSEGV);
+ sigprocmask (how, &sigs, (sigset_t *) 0);
}
-/* Update the mtab by removing any DIR entries and replace it with INSTEAD. */
-void
-update_mtab (const char *dir, struct mntent *instead)
-{
- struct mntent *mnt;
- struct mntent *next;
- int added = 0;
- open_mtab ("r");
+/* Non-fatal error. Print message and return. */
+/* (print the message in a single printf, in an attempt
+ to avoid mixing output of several threads) */
+void
+error (const char *fmt, ...) {
+ va_list args;
+ char *fmt2;
- if ((F_temp = setmntent (MOUNTED_TEMP, "w")) == NULL)
- die (2, "can't open %s: %s", MOUNTED_TEMP, strerror (errno));
-
- while ((mnt = getmntent (F_mtab)))
- {
- next = streq (mnt->mnt_dir, dir) ? (added++, instead) : mnt;
- if (next && addmntent(F_temp, next) == 1)
- die (1, "error writing %s: %s", MOUNTED_TEMP, strerror (errno));
- }
- if (instead && !added)
- addmntent(F_temp, instead);
-
- endmntent (F_mtab);
- if (fchmod (fileno (F_temp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "error changing mode of %s: %s", MOUNTED_TEMP, strerror (errno));
- endmntent (F_temp);
-
- if (rename (MOUNTED_TEMP, MOUNTED) < 0)
- die (1, "can't rename %s to %s: %s",
- MOUNTED_TEMP, MOUNTED, strerror(errno));
+ if (mount_quiet)
+ return;
+ fmt2 = xstrconcat2 (fmt, "\n");
+ va_start (args, fmt);
+ vfprintf (stderr, fmt2, args);
+ va_end (args);
+ free (fmt2);
}
-/* Given the name FILE, try to find it in mtab. */
-struct mntent *
-getmntfile (const char *file)
-{
- struct mntent *mnt;
-
- if (!F_mtab)
- return NULL;
-
- rewind(F_mtab);
+/* Fatal error. Print message and exit. */
+void
+die (int err, const char *fmt, ...) {
+ va_list args;
- while ((mnt = getmntent (F_mtab)) != NULL)
- {
- if (streq (mnt->mnt_dir, file))
- break;
- if (streq (mnt->mnt_fsname, file))
- break;
- }
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+ va_end (args);
- return mnt;
+ unlock_mtab ();
+ exit (err);
}
/* Parse a list of strings like str[,str]... into a string list. */
string_list
-parse_list (char *strings)
-{
- string_list list;
- char *t;
+parse_list (char *strings) {
+ string_list list;
+ char *t;
- if (strings == NULL)
- return NULL;
+ if (strings == NULL)
+ return NULL;
- list = cons (strtok (strings, ","), NULL);
+ list = cons (strtok (strings, ","), NULL);
- while ((t = strtok (NULL, ",")) != NULL)
- list = cons (t, list);
+ while ((t = strtok (NULL, ",")) != NULL)
+ list = cons (t, list);
- return list;
+ return list;
}
/* True if fstypes match. Null *TYPES means match anything,
- except that swap types always return false. This routine
- has some ugliness to deal with ``no'' types. */
+ except that swap types always return false.
+ This routine has some ugliness to deal with ``no'' types.
+ Fixed bug: the `no' part comes at the end - aeb, 970216 */
int
-matching_type (const char *type, string_list types)
-{
- char *notype;
- int no; /* true if a "no" type match, ie -t nominix */
-
- if (streq (type, MNTTYPE_SWAP))
- return 0;
- if (types == NULL)
- return 1;
-
- if ((notype = alloca (strlen (type) + 3)) == NULL)
- die (2, "mount: out of memory");
- sprintf (notype, "no%s", type);
- no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
-
- /* If we get a match and the user specified a positive match type (e.g.
- "minix") we return true. If we match and a negative match type (e.g.
- "nominix") was specified we return false. */
- while (types != NULL)
- if (streq (type, car (types)))
- return !no;
- else if (streq (notype, car (types)))
- return 0; /* match with "nofoo" always returns false */
- else
- types = cdr (types);
-
- /* No matches, so if the user specified a positive match type return false,
- if a negative match type was specified, return true. */
- return no;
+matching_type (const char *type, string_list types) {
+ char *notype;
+ int foundyes, foundno;
+ int no; /* true if a "no" type match, eg -t nominix */
+
+ if (streq (type, MNTTYPE_SWAP))
+ return 0;
+ if (types == NULL)
+ return 1;
+
+ if ((notype = alloca (strlen (type) + 3)) == NULL)
+ die (EX_SYSERR, "mount: out of memory");
+ sprintf (notype, "no%s", type);
+
+ foundyes = foundno = no = 0;
+ while (types != NULL) {
+ if (cdr (types) == NULL)
+ no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
+ if (streq (type, car (types)))
+ foundyes = 1;
+ else if (streq (notype, car (types)))
+ foundno = 1;
+ types = cdr (types);
+ }
+
+ return (foundno ? 0 : (no ^ foundyes));
}
/* Make a canonical pathname from PATH. Returns a freshly malloced string.
It is up the *caller* to ensure that the PATH is sensible. i.e.
canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
- is not a legal pathname for ``/dev/fd0.'' Anything we cannot parse
+ is not a legal pathname for ``/dev/fd0''. Anything we cannot parse
we return unmodified. */
char *
-canonicalize (const char *path)
-{
- char *canonical = xmalloc (PATH_MAX + 1);
+canonicalize (const char *path) {
+ char *canonical;
- if (path == NULL)
- return NULL;
+ if (path == NULL)
+ return NULL;
+
+ if (streq(path, "none") || streq(path, "proc"))
+ return xstrdup(path);
+
+ canonical = xmalloc (PATH_MAX + 1);
- if (realpath (path, canonical))
- return canonical;
+ if (realpath (path, canonical))
+ return canonical;
- strcpy (canonical, path);
- return canonical;
+ free(canonical);
+ return xstrdup(path);
}