summaryrefslogtreecommitdiffstats
path: root/mount/sundries.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount/sundries.c')
-rw-r--r--mount/sundries.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/mount/sundries.c b/mount/sundries.c
new file mode 100644
index 000000000..45e0e14d8
--- /dev/null
+++ b/mount/sundries.c
@@ -0,0 +1,283 @@
+/*
+ * Support functions. Exported functions are prototyped in sundries.h.
+ * sundries.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ */
+
+#include "sundries.h"
+
+/* File pointer for /etc/mtab. */
+FILE *F_mtab = NULL;
+
+/* File pointer for temp mtab. */
+FILE *F_temp = NULL;
+
+/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
+static int lock = -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);
+
+ car (p) = a;
+ cdr (p) = b;
+ return p;
+}
+
+void *
+xmalloc (size_t size)
+{
+ void *t;
+
+ if (size == 0)
+ return NULL;
+
+ t = malloc (size);
+ if (t == NULL)
+ die (2, "not enough memory");
+
+ return t;
+}
+
+char *
+xstrdup (const char *s)
+{
+ char *t;
+
+ if (s == NULL)
+ return NULL;
+
+ t = strdup (s);
+
+ if (t == NULL)
+ die (2, "not enough memory");
+
+ return t;
+}
+
+/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
+void
+block_signals (int how)
+{
+ sigset_t sigs;
+
+ sigfillset (&sigs);
+ sigprocmask (how, &sigs, (sigset_t *) 0);
+}
+
+
+/* Non-fatal error. Print message and return. */
+void
+error (const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+}
+
+/* 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);
+
+ unlock_mtab ();
+ exit (err);
+}
+
+/* Ensure that the lock is released if we are interrupted. */
+static void
+handler (int sig)
+{
+ die (2, "%s", sys_siglist[sig]);
+}
+
+/* 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;
+
+ /* If this is the first time, ensure that the lock will be removed. */
+ if (lock < 0)
+ {
+ 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));
+ }
+}
+
+/* Remove lock file. */
+void
+unlock_mtab (void)
+{
+ if (lock != -1)
+ {
+ close( lock );
+ unlink (MOUNTED_LOCK);
+ }
+}
+
+/* Open mtab. */
+void
+open_mtab (const char *mode)
+{
+ if ((F_mtab = setmntent (MOUNTED, mode)) == NULL)
+ die (2, "can't open %s: %s", MOUNTED, strerror (errno));
+}
+
+/* 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);
+}
+
+/* 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");
+
+ 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));
+}
+
+/* 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);
+
+ while ((mnt = getmntent (F_mtab)) != NULL)
+ {
+ if (streq (mnt->mnt_dir, file))
+ break;
+ if (streq (mnt->mnt_fsname, file))
+ break;
+ }
+
+ return mnt;
+}
+
+/* Parse a list of strings like str[,str]... into a string list. */
+string_list
+parse_list (char *strings)
+{
+ string_list list;
+ char *t;
+
+ if (strings == NULL)
+ return NULL;
+
+ list = cons (strtok (strings, ","), NULL);
+
+ while ((t = strtok (NULL, ",")) != NULL)
+ list = cons (t, 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. */
+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;
+}
+
+/* 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
+ we return unmodified. */
+char *
+canonicalize (const char *path)
+{
+ char *canonical = xmalloc (PATH_MAX + 1);
+
+ if (path == NULL)
+ return NULL;
+
+ if (realpath (path, canonical))
+ return canonical;
+
+ strcpy (canonical, path);
+ return canonical;
+}