utils: Make mount/umount do all the right things
authorAlan Cox <alan@linux.intel.com>
Sun, 31 Dec 2017 22:22:57 +0000 (22:22 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 31 Dec 2017 22:22:57 +0000 (22:22 +0000)
Now uses mntent, does proper locking and correctly allows mount and umount -a

Applications/util/mount.c
Applications/util/prtroot.c
Applications/util/umount.c

index 01b6c16..b07f8c3 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <mntent.h>
+#include <sys/mount.h>
 
-/* Assumed length of a line in /etc/mtab */
-#define MTAB_LINE 160
+static int err = 0;
+static int all = 0;
+static char *fstype = "fuzix";
 
-int lsmtab(void)
+static void usage(void)
+{
+    fputs("Usage: mount [-a] [-t type] name [path].\n", stderr);
+    exit(1);
+}
+
+static int lsmtab(void)
 {
     FILE *f;
-       char tmp[MTAB_LINE];
-       char* dev;
-       char* mntpt;
-       char* fstype;
-       char* rwflag;
+    struct mntent *mnt;
     
-    f = fopen("/etc/mtab", "r");
+    f = setmntent("/etc/mtab", "r");
     if (f) {
-        while (fgets(tmp, sizeof(tmp), f)) {
-                       dev = strtok(tmp, " ");
-                       mntpt = strtok(NULL, " ");
-                       fstype = strtok(NULL, " ");
-                       rwflag = strtok(NULL, "\n");
-            if (strcmp(fstype, "swap") == 0)
-                printf("%s is swapspace\n", dev);
+        while (mnt = getmntent(f)) {
+            if (strcmp(mnt->mnt_type, "swap") == 0)
+                printf("%s is swapspace\n", mnt->mnt_fsname);
             else
-                printf("%s mounted on %s read-%s\n", dev, mntpt,
-                       (strcmp(rwflag, "ro") == 0) ? "only" : "write");
+                printf("%s mounted on %s read-%s\n",
+                    mnt->mnt_fsname,
+                    mnt->mnt_dir,
+                    hasmntopt(mnt, "ro") ? "only" : "write");
         }
-        fclose(f);
-    }
+        endmntent(f);
+    } else
+        err = 1;
     
     return 0;
 }
 
-int add2mtab(char *dev, char *mntpt, char *fstype, char *rwflag)
+static void add2mtab(struct mntent *mnt)
 {
-    FILE *inpf, *outf;
-    char *tmp_fname;
-       int c;
+    FILE *f;
 
-    if ((tmp_fname = tmpnam(NULL)) == NULL) {
-        perror("Error getting temporary file name");
-        exit(1);
-    }
-    inpf = fopen("/etc/mtab", "r");
-    outf = fopen(tmp_fname, "w");
-    if (!outf) {
-        perror("Can't create temporary file");
+    f = setmntent("/etc/mtab", "a");
+    if (f == NULL) {
+        perror("/etc/mtab");
         exit(1);
     }
-    if (inpf) {
-               for (;;) {
-                       c = fgetc(inpf);
-                       if (c == EOF)
-                               break;
-                       fputc(c, outf);
+    addmntent(f, mnt);
+    endmntent(f);
+}
+
+static int flagsof(struct mntent *mnt)
+{
+    int f = 0;
+    if (hasmntopt(mnt, "ro"))
+        f |= MS_RDONLY;
+    if (hasmntopt(mnt, "nosuid"))
+        f |= MS_NOSUID;
+    return f;
+}
+
+static int is_mounted(struct mntent *ent)
+{
+    FILE *f = setmntent("/etc/mtab", "r");
+    struct mntent mnt;
+    static char buf[_MAX_MNTLEN];
+    
+    while(getmntent_r(f, &mnt, buf, _MAX_MNTLEN)) {
+        if (strcmp(mnt.mnt_fsname, ent->mnt_fsname) == 0) {
+            endmntent(f);
+            return 1;
         }
-        fclose(inpf);
     }
-    fprintf(outf, "%s %s %s %s\n", dev, mntpt, fstype, rwflag);
-    fclose(outf);
-    if (inpf && unlink("/etc/mtab") < 0) {
-        perror("Can't delete old /etc/mtab file");
-        exit(1);
+    endmntent(f);
+    return 0;
+}
+
+static void do_mount(struct mntent *mnt)
+{
+    if (strcmp(mnt->mnt_type, "swap") == 0)
+        return;
+    if (mount(mnt->mnt_fsname, mnt->mnt_dir, flagsof(mnt)) == -1) {
+        err = errno;
+        perror(mnt->mnt_fsname);
+        return;
     }
-    if (rename(tmp_fname, "/etc/mtab") < 0) {
-        perror("Error installing /etc/mtab");
-        exit(1);
+    add2mtab(mnt);
+}
+
+static void automount(char *match)
+{
+    FILE *f = setmntent("/etc/fstab", "r");
+    struct mntent *mnt;
+
+    while (mnt = getmntent(f)) {
+        /* Warning - mnt contents go invalid if we do work on mtab so
+           be careful here and use getmntent_r in is_mounted */
+        if (is_mounted(mnt))
+            continue;
+        if (match == NULL || strcmp(mnt->mnt_fsname, match) == 0 ||
+                                strcmp(mnt->mnt_dir, match) == 0)
+                do_mount(mnt);
+        if (err)
+            break;
     }
-    return 0;
+    endmntent(f);
 }
 
 int main(int argc, char *argv[])
 {
-    if (argc == 1) {
-        lsmtab();
-        return 0;
-    }
+    int opt;
 
-    if (argc != 3) {
-        printf("usage: mount device path\n");
-        return 1;
+    while((opt = getopt(argc, argv, "at:")) != -1) {
+        if (opt == 'a')
+            all = 1;
+        else if (opt == 't')
+            fstype = optarg;
+        else
+            usage();
     }
 
-    if (mount(argv[1], argv[2], 0) == 0) {
-        add2mtab(argv[1], argv[2], "uzi", "rw");
-    } else {
-        perror("mount");
-        return 1;
+    if (optind >= argc) {
+        if (all)
+            automount(NULL);
+        else
+            lsmtab();
+        return err;
     }
-    return 0;
+    if (optind == argc - 1)
+        automount(argv[optind]);
+    else if (optind <= argc - 2) {
+        static struct mntent mnt;
+        mnt.mnt_fsname = argv[optind++];
+        mnt.mnt_dir = argv[optind++];
+        mnt.mnt_type = fstype;
+        if (optind != argc)
+            mnt.mnt_opts = argv[optind++];
+        if (optind != argc)
+            usage();
+        do_mount(&mnt);
+    }
+    return err;
 }
index 6be4b66..34e7b77 100644 (file)
@@ -27,7 +27,7 @@
 #include <dirent.h>
 
 #define DEV_PATH       "/dev/"
-#define MESSAGE                " / fuzix rw\n"
+#define MESSAGE                " / fuzix rw 0 0\n"
 #define UNKNOWN_DEV    "/dev/unknown"
 #define ROOT           "/"
 
index 77ac925..cee0c54 100644 (file)
@@ -2,49 +2,35 @@
 #include <string.h>
 #include <stdlib.h>
 #include <sys/mount.h>
+#include <mntent.h>
 
 /* Assumed length of a line in /etc/mtab */
+/* FIXME */
 #define MTAB_LINE 160
 #define MAXFS  16
 
 static char *devlist[MAXFS];
 static char **devp = &devlist[0];
 
-static char tmp[MTAB_LINE];
-
-const char *readmtab(FILE *fp)
-{
-    char *dev;
-    while (fgets(tmp, sizeof(tmp), fp) != NULL) {
-        dev = strtok(tmp, " \t");
-        if (dev == NULL || *tmp == '#')
-            continue;
-        return dev;
-    }
-    return NULL;
-}
-
-char *getdev(char *arg)
+static char *getdev(char *arg)
 {
        FILE *f;
-       const char *dev;
-       char* mntpt;
+       struct mntent *mnt;
 
-       f = fopen("/etc/mtab", "r");
+       f = setmntent("/etc/mtab", "r");
        if (f) {
-               while ((dev = readmtab(f)) != NULL) {
-                       mntpt = strtok(NULL, " \t");
-                       if ((strcmp(dev, arg) == 0) || (strcmp(mntpt, arg) == 0)) {
-                               fclose(f);
-                               return strdup(dev);
+               while (mnt = getmntent(f)) {
+                       if ((strcmp(mnt->mnt_fsname, arg) == 0) || (strcmp(mnt->mnt_dir, arg) == 0)) {
+                               endmntent(f);
+                               return strdup(mnt->mnt_fsname);
                        }
                }
-               fclose(f);
+               endmntent(f);
        }
        return NULL;
 }
 
-int deleted(const char *p)
+static int deleted(const char *p)
 {
        char **d = &devlist[0];
 
@@ -65,35 +51,30 @@ static void queue_rm_mtab(const char *p)
 }
 
 /* FIXME: error checking, atomicity */
-int rewrite_mtab(void)
+static int rewrite_mtab(void)
 {
        FILE *inpf, *outf;
-       char *tmp_fname;
-       static char tmp[MTAB_LINE];
-       static char tmp2[MTAB_LINE];
-       char* dev;
+       struct mntent *mnt;
 
-       inpf = fopen("/etc/mtab", "r");
+       inpf = setmntent("/etc/mtab", "r");
        if (!inpf) {
                perror("Can't open /etc/mtab");
                exit(1);
        }
-       outf = fopen("/etc/mtab.new", "w");
+       outf = setmntent("/etc/mtab.new", "w");
        if (!outf) {
                perror("Can't create temporary file");
                exit(1);
        }
-       while (fgets(tmp, sizeof(tmp), inpf)) {
-               strncpy( tmp2, tmp, MTAB_LINE );
-               dev = strtok(tmp, " \t");
-               if (dev && deleted(dev)) {
+       while (mnt = getmntent(inpf)) {
+               /* FIXME: should we check device and dir ? */
+               if (deleted(mnt->mnt_fsname))
                        continue;
-               } else {
-                       fputs(tmp2, outf);
-               }
+               else
+                       addmntent(outf, mnt);
        }
-       fclose(inpf);
-       fclose(outf);
+       endmntent(inpf);
+       endmntent(outf);
        if (rename("/etc/mtab.new", "/etc/mtab") < 0) {
                perror("Error installing /etc/mtab");
                exit(1);
@@ -103,6 +84,7 @@ int rewrite_mtab(void)
 
 int main(int argc, char *argv[])
 {
+       struct mntent *mnt;
        const char *dev;
        char **dp;
        FILE *f;
@@ -117,18 +99,17 @@ int main(int argc, char *argv[])
        if (strcmp(argv[1], "-a") == 0) {
                /* We need to umount things in reverse order if we have
                   mounts on mounts */
-               f = fopen("/etc/mtab", "r");
+               f = setmntent("/etc/mtab", "r");
                if (f == NULL) {
                        perror("mtab");
                        exit(1);
                }
-               while((dev = readmtab(f)) != NULL) {
-                       char *mntpt = strtok(NULL, " \t");
+               while(mnt = getmntent(f)) {
                        /* We can't unmount / */
-                       if (strcmp(mntpt, "/"))
-                               queue_rm_mtab(dev);
+                       if (strcmp(mnt->mnt_dir, "/"))
+                               queue_rm_mtab(mnt->mnt_fsname);
                }
-               fclose(f);
+               endmntent(f);
                dp = devp;
                /* Unmount in reverse order of mounting */
                while(--dp >= devlist) {