remount, umount: updates for mtab
authorAlan Cox <alan@linux.intel.com>
Sun, 12 Nov 2017 21:33:45 +0000 (21:33 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 12 Nov 2017 21:33:45 +0000 (21:33 +0000)
Fix parsing in remount
Add umount -a support to the umount tool

Applications/util/remount.c
Applications/util/umount.c

index 9a9ad3c..0b846a9 100644 (file)
@@ -17,7 +17,11 @@ char *getdev(char *arg)
        if (f) {
                while (fgets(tmp, sizeof(tmp), f)) {
                        dev = strtok(tmp, " \t");
+                       if (*tmp == '#' || dev == NULL)
+                               continue;
                        mntpt = strtok(NULL, " \t");
+                       if (mntpt == NULL)
+                               continue;
                        if ((strcmp(dev, arg) == 0) || (strcmp(mntpt, arg) == 0)) {
                                fclose(f);
                                return strdup(dev);
index 273d881..77ac925 100644 (file)
@@ -5,19 +5,35 @@
 
 /* Assumed length of a line in /etc/mtab */
 #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)
 {
        FILE *f;
-       char tmp[MTAB_LINE];
-       char* dev;
+       const char *dev;
        char* mntpt;
 
        f = fopen("/etc/mtab", "r");
        if (f) {
-               while (fgets(tmp, sizeof(tmp), f)) {
-                       dev = strtok(tmp, " ");
-                       mntpt = strtok(NULL, " ");
+               while ((dev = readmtab(f)) != NULL) {
+                       mntpt = strtok(NULL, " \t");
                        if ((strcmp(dev, arg) == 0) || (strcmp(mntpt, arg) == 0)) {
                                fclose(f);
                                return strdup(dev);
@@ -28,8 +44,28 @@ char *getdev(char *arg)
        return NULL;
 }
 
+int deleted(const char *p)
+{
+       char **d = &devlist[0];
 
-int rm_mtab(char *devname)
+       while(d < devp) {
+               if (*d && strcmp(*d, p) == 0)
+                       return 1;
+               d++;
+       }
+       return 0;
+}
+
+static void queue_rm_mtab(const char *p)
+{
+       if (devp == &devlist[MAXFS])
+               fputs("umount: too many file systems.\n", stderr);
+       else
+               *devp++ = strdup(p);
+}
+
+/* FIXME: error checking, atomicity */
+int rewrite_mtab(void)
 {
        FILE *inpf, *outf;
        char *tmp_fname;
@@ -37,36 +73,28 @@ int rm_mtab(char *devname)
        static char tmp2[MTAB_LINE];
        char* dev;
 
-       if ((tmp_fname = tmpnam(NULL)) == NULL) {
-               perror("Error getting temporary file name");
-               exit(1);
-       }
        inpf = fopen("/etc/mtab", "r");
        if (!inpf) {
                perror("Can't open /etc/mtab");
                exit(1);
        }
-       outf = fopen(tmp_fname, "w");
+       outf = fopen("/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, " ");
-               if (strcmp(dev, devname) == 0) {
+               dev = strtok(tmp, " \t");
+               if (dev && deleted(dev)) {
                        continue;
                } else {
-                       fprintf(outf, "%s", tmp2);
+                       fputs(tmp2, outf);
                }
        }
        fclose(inpf);
        fclose(outf);
-       if (unlink("/etc/mtab") < 0) {
-               perror("Can't delete old /etc/mtab file");
-               exit(1);
-       }
-       if (rename(tmp_fname, "/etc/mtab") < 0) {
+       if (rename("/etc/mtab.new", "/etc/mtab") < 0) {
                perror("Error installing /etc/mtab");
                exit(1);
        }
@@ -75,21 +103,53 @@ int rm_mtab(char *devname)
 
 int main(int argc, char *argv[])
 {
-       char *dev;
+       const char *dev;
+       char **dp;
+       FILE *f;
+       int err = 0;
+
+       umask(022);
        
        if (argc != 2) {
                fprintf(stderr, "%s: umount device\n", argv[0]);
                return 1;
        }
-
-       dev = getdev(argv[1]);
-       if (!dev) dev = argv[1];
-       
-       if (umount(dev) == 0) {
-               rm_mtab(dev);
+       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");
+               if (f == NULL) {
+                       perror("mtab");
+                       exit(1);
+               }
+               while((dev = readmtab(f)) != NULL) {
+                       char *mntpt = strtok(NULL, " \t");
+                       /* We can't unmount / */
+                       if (strcmp(mntpt, "/"))
+                               queue_rm_mtab(dev);
+               }
+               fclose(f);
+               dp = devp;
+               /* Unmount in reverse order of mounting */
+               while(--dp >= devlist) {
+                       if (umount(*dp) == -1) {
+                               perror(*dp);
+                               *dp = NULL;
+                               err |= 1;
+                       }
+               }
+               rewrite_mtab();
        } else {
-               perror("umount");
+               dev = getdev(argv[1]);
+               if (!dev)
+                       dev = argv[1];
+
+               if (umount(dev) == 0) {
+                       queue_rm_mtab(dev);
+                       rewrite_mtab();
+               } else
+                       perror("umount");
                return 1;
        }
-       return 0;
+       return err;
 }