Forgot some debugging noise.
[oweals/busybox.git] / umount.c
index 4efc9f9d90b9422a28ef9648b92072dc152fab2e..68b27e385d62fb1eb86435a7aa93b204ed142a8e 100644 (file)
--- a/umount.c
+++ b/umount.c
+/*
+ * Mini umount implementation for busybox
+ *
+ *
+ * Copyright (C) 1999 by Lineo, inc.
+ * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include "internal.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
 #include <stdio.h>
-#include <mntent.h>
 #include <sys/mount.h>
+#include <mntent.h>
+#include <fstab.h>
+#include <errno.h>
 
-const char     umount_usage[] = "umount {filesystem|directory}\n"
-"\tumount -a\n"
+static const char umount_usage[] = 
+"umount [flags] filesystem|directory\n\n"
+"Flags:\n"
+"\t-a:\tUnmount all file systems"
+#ifdef BB_MTAB
+" in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n"
+#else
 "\n"
-"\tUnmount a filesystem.\n"
-"\t-a:\tUnmounts all mounted filesystems.\n";
+#endif
+;
 
-static char *
-stralloc(const char * string)
-{
-       int     length = strlen(string) + 1;
-       char *  n = malloc(length);
-       memcpy(n, string, length);
-       return n;
-}
 
-extern void
-erase_mtab(const char * name)
+static int useMtab = TRUE;
+static int umountAll = FALSE;
+extern const char mtab_file[]; /* Defined in utility.c */
+
+#define MIN(x,y) (x > y ? x : y)
+
+static int 
+do_umount(const char* name, int useMtab)
 {
-       struct mntent   entries[100];
-       int             count = 0;
-       FILE *          mountTable = setmntent("/etc/mtab", "r");
-       struct mntent * m;
-
-       if ( mountTable == 0
-        && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) {
-               name_and_error("/etc/mtab");
-               return;
-       }
+    int status;
+    struct mntent *m;
+    FILE *mountTable;
+    const char *blockDevice = NULL;
 
-       while ( (m = getmntent(mountTable)) != 0 ) {
-               entries[count].mnt_fsname = stralloc(m->mnt_fsname);
-               entries[count].mnt_dir = stralloc(m->mnt_dir);
-               entries[count].mnt_type = stralloc(m->mnt_type);
-               entries[count].mnt_opts = stralloc(m->mnt_opts);
-               entries[count].mnt_freq = m->mnt_freq;
-               entries[count].mnt_passno = m->mnt_passno;
-               count++;
-       }
-       endmntent(mountTable);
-       if ( (mountTable = setmntent("/etc/mtab", "w")) ) {
-               int     i;
-               for ( i = 0; i < count; i++ ) {
-                       int result = ( strcmp(entries[i].mnt_fsname, name) == 0
-                        || strcmp(entries[i].mnt_dir, name) == 0 );
-
-                       if ( result )
-                               continue;
-                       else
-                               addmntent(mountTable, &entries[i]);
-               }
-               endmntent(mountTable);
+    if ((mountTable = setmntent (mtab_file, "r"))) {
+       while ((m = getmntent (mountTable)) != 0) {
+           if (strncmp(m->mnt_dir, name,
+                       MIN(strlen(m->mnt_dir),strlen(name))) == 0)
+               blockDevice = m->mnt_fsname;
+           else if (strcmp(m->mnt_fsname, name) == 0) {
+               blockDevice = name;
+               name = m->mnt_dir;
+           }
        }
-       else if ( errno != EROFS )
-               name_and_error("/etc/mtab");
+    }
+
+    status = umount(name);
+
+#if defined BB_FEATURE_MOUNT_LOOP
+    if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
+       /* this was a loop device, delete it */
+       del_loop(blockDevice);
+#endif
+#if defined BB_MTAB
+    if ( status == 0 ) {
+       if ( useMtab==TRUE )
+           erase_mtab(name);
+       return 0;
+    }
+    else
+#endif
+       return(status);
 }
 
 static int
-umount_all(int noMtab)
+umount_all(int useMtab)
 {
-       struct mntent   entries[100];
-       int                             count = 0;
-       FILE *                  mountTable = setmntent("/etc/mtab", "r");
-       struct mntent * m;
-       int                             status = 0;
-
-       if ( mountTable == 0
-        && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) {
-               name_and_error("/etc/mtab");
-               return 1;
-       }
+       int status;
+       struct mntent *m;
+        FILE *mountTable;
 
-       while ( (m = getmntent(mountTable)) != 0 ) {
-               entries[count].mnt_fsname = stralloc(m->mnt_fsname);
-               count++;
-       }
-       endmntent(mountTable);
-
-       while ( count > 0 ) {
-               int result = umount(entries[--count].mnt_fsname) == 0;
-               /* free(entries[count].mnt_fsname); */
-               if ( result ) {
-                       if ( !noMtab )
-                               erase_mtab(entries[count].mnt_fsname);
+        if ((mountTable = setmntent (mtab_file, "r"))) {
+            while ((m = getmntent (mountTable)) != 0) {
+                char *blockDevice = m->mnt_fsname;
+#if ! defined BB_MTAB
+               if (strcmp (blockDevice, "/dev/root") == 0) {
+                   struct fstab* fstabItem;
+                   fstabItem = getfsfile ("/");
+                   if (fstabItem != NULL) {
+                       blockDevice = fstabItem->fs_spec;
+                   }
                }
-               else {
-                       status = 1;
-                       name_and_error(entries[count].mnt_fsname);
+#endif
+               /* Don't umount /proc when doing umount -a */
+                if (strcmp (blockDevice, "proc") == 0)
+                   continue;
+
+               status=do_umount (m->mnt_dir, useMtab);
+               if (status!=0) {
+                   /* Don't bother retrying the umount on busy devices */
+                   if (errno==EBUSY) {
+                       perror(m->mnt_dir); 
+                       continue;
+                   }
+                   status=do_umount (blockDevice, useMtab);
+                   if (status!=0) {
+                       printf ("Couldn't umount %s on %s (type %s): %s\n", 
+                               blockDevice, m->mnt_dir, m->mnt_type, strerror(errno));
+                   }
                }
-       }
-       return status;
+            }
+            endmntent (mountTable);
+        }
+        return( TRUE);
 }
 
 extern int
-do_umount(const char * name, int noMtab)
+umount_main(int argc, char** argv)
 {
-       if ( umount(name) == 0 ) {
-               if ( !noMtab )
-                       erase_mtab(name);
-               return 0;
-       }
-       return 1;
-}
+    if (argc < 2) {
+       usage( umount_usage); 
+    }
 
-extern int
-umount_main(struct FileInfo * i, int argc, char * * argv)
-{
-       int     noMtab = 0;
-
-       if ( argv[1][0] == '-' ) {
-               switch ( argv[1][1] ) {
-               case 'a':
-                       return umount_all(noMtab);
-               case 'n':
-                       noMtab = 1;
-                       break;
-               default:
-                       usage(umount_usage);
-                       return 1;
-               }
+    /* Parse any options */
+    while (--argc > 0 && **(++argv) == '-') {
+       while (*++(*argv)) switch (**argv) {
+           case 'a':
+               umountAll = TRUE;
+               break;
+#ifdef BB_MTAB
+           case 'n':
+               useMtab = FALSE;
+               break;
+#endif
+           default:
+               usage( umount_usage);
        }
-       if ( do_umount(argv[1],noMtab) != 0 ) {
-               fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno));
-               return 1;
-       }
-       return 0;
+    }
+
+
+    if(umountAll==TRUE) {
+       exit(umount_all(useMtab));
+    }
+    if ( do_umount(*argv,useMtab) == 0 )
+       exit (TRUE);
+    else {
+       perror("umount");
+       exit(FALSE);
+    }
 }
+