- int status;
- struct mntent *m;
- FILE *mountTable;
-
- 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;
- }
+ int doForce;
+ char path[2*PATH_MAX];
+ struct mntent me;
+ FILE *fp;
+ int status = EXIT_SUCCESS;
+ unsigned opt;
+ struct mtab_list {
+ char *dir;
+ char *device;
+ struct mtab_list *next;
+ } *mtl, *m;
+
+ /* Parse any options */
+
+ opt = getopt32(argc, argv, OPTION_STRING);
+
+ argc -= optind;
+ argv += optind;
+
+ doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY));
+
+ /* Get a list of mount points from mtab. We read them all in now mostly
+ * for umount -a (so we don't have to worry about the list changing while
+ * we iterate over it, or about getting stuck in a loop on the same failing
+ * entry. Notice that this also naturally reverses the list so that -a
+ * umounts the most recent entries first. */
+
+ m = mtl = 0;
+
+ /* If we're umounting all, then m points to the start of the list and
+ * the argument list should be empty (which will match all). */
+
+ fp = setmntent(bb_path_mtab_file, "r");
+ if (!fp) {
+ if (opt & OPT_ALL)
+ bb_error_msg_and_die("cannot open %s", bb_path_mtab_file);
+ } else {
+ while (getmntent_r(fp, &me, path, sizeof(path))) {
+ m = xmalloc(sizeof(struct mtab_list));
+ m->next = mtl;
+ m->device = xstrdup(me.mnt_fsname);
+ m->dir = xstrdup(me.mnt_dir);
+ mtl = m;
+ }
+ endmntent(fp);
+ }
+
+ /* If we're not umounting all, we need at least one argument. */
+ if (!(opt & OPT_ALL)) {
+ m = 0;
+ if (!argc) bb_show_usage();
+ }
+
+ // Loop through everything we're supposed to umount, and do so.
+ for (;;) {
+ int curstat;
+ char *zapit = *argv;
+
+ // Do we already know what to umount this time through the loop?
+ if (m) safe_strncpy(path, m->dir, PATH_MAX);
+ // For umount -a, end of mtab means time to exit.
+ else if (opt & OPT_ALL) break;
+ // Get next command line argument (and look it up in mtab list)
+ else if (!argc--) break;
+ else {
+ argv++;
+ realpath(zapit, path);
+ for (m = mtl; m; m = m->next)
+ if (!strcmp(path, m->dir) || !strcmp(path, m->device))
+ break;