From 25fe0e0bea85f1d851ce03a90c0f1bf41ab431f2 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 7 Sep 2014 14:42:51 -0500 Subject: Debugging pass on mount. Not quite done yet, but the basics seem to work now. --- lib/getmountlist.c | 8 +++--- toys/pending/mount.c | 73 ++++++++++++++++++++++++++-------------------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/getmountlist.c b/lib/getmountlist.c index a88a7b90..98347223 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -31,7 +31,7 @@ char *comma_iterate(char **list, int *len) { char *start = *list, *end; - if (!*list) return 0; + if (!*list || !**list) return 0; if (!(end = strchr(*list, ','))) { *len = strlen(*list); @@ -76,8 +76,10 @@ int comma_scan(char *optlist, char *opt, int clean) if (!s) break; no = 2*(*s == 'n' && s[1] == 'o'); - if (optlen == len+no && !strcmp(opt, s+no)) got = !no; - if (clean) memmove(s, optlist, strlen(optlist)+1); + if (optlen == len+no && !strcmp(opt, s+no)) { + got = !no; + if (clean) memmove(s, optlist, strlen(optlist)+1); + } } return got; diff --git a/toys/pending/mount.c b/toys/pending/mount.c index e279db37..53b16bc7 100644 --- a/toys/pending/mount.c +++ b/toys/pending/mount.c @@ -139,7 +139,7 @@ static void mount_filesystem(char *dev, char *dir, char *type, } // Autodetect bind mount or filesystem type - if (!type || !strcmp(type, "auto")) { + if (!(flags & MS_MOVE) && (!type || !strcmp(type, "auto"))) { struct stat stdev, stdir; // file on file or dir on dir is a --bind mount. @@ -182,43 +182,43 @@ static void mount_filesystem(char *dev, char *dir, char *type, } free(buf); - if (rc) { - // Trying to autodetect loop mounts like bind mounts above (file on dir) - // isn't good enough because "mount -t ext2 fs.img dir" is valid, but if - // you _do_ accept loop mounts with -t how do you tell "-t cifs" isn't - // looking for a block device if it's not in /proc/filesystems yet - // because the module that won't be loaded until you try the mount, and - // if you can't then DEVICE existing as a file would cause a false - // positive loopback mount (so "touch servername" becomes a potential - // denial of service attack...) - // - // Solution: try the mount, let the kernel tell us it wanted a block - // device, then do the loopback setup and retry the mount. - - if (fp && errno == EINVAL) continue;; - - if (errno == ENOTBLK) { - char *losetup[] = {"losetup", "-fs", dev, 0}; - int pipes[2], len; - pid_t pid; - - if (flags & MS_RDONLY) losetup[1] = "-fsr"; - pid = xpopen(losetup, pipes); - len = readall(pipes[1], toybuf, sizeof(toybuf)-1); - rc = xpclose(pid, pipes); - if (!rc && len > 1) { - if (toybuf[len-1] == '\n') --len; - toybuf[len] = 0; - dev = toybuf; + if (!rc) break; + + // Trying to autodetect loop mounts like bind mounts above (file on dir) + // isn't good enough because "mount -t ext2 fs.img dir" is valid, but if + // you _do_ accept loop mounts with -t how do you tell "-t cifs" isn't + // looking for a block device if it's not in /proc/filesystems yet + // because the module that won't be loaded until you try the mount, and + // if you can't then DEVICE existing as a file would cause a false + // positive loopback mount (so "touch servername" becomes a potential + // denial of service attack...) + // + // Solution: try the mount, let the kernel tell us it wanted a block + // device, then do the loopback setup and retry the mount. + + if (fp && errno == EINVAL) continue; + + if (errno == ENOTBLK) { + char *losetup[] = {"losetup", "-fs", dev, 0}; + int pipes[2], len; + pid_t pid; + + if (flags & MS_RDONLY) losetup[1] = "-fsr"; + pid = xpopen(losetup, pipes); + len = readall(pipes[1], toybuf, sizeof(toybuf)-1); + rc = xpclose(pid, pipes); + if (!rc && len > 1) { + if (toybuf[len-1] == '\n') --len; + toybuf[len] = 0; + dev = toybuf; - continue; - } else error_msg("losetup failed %d", rc); - } else perror_msg("'%s'->'%s'", dev, dir); - } + continue; + } else error_msg("losetup failed %d", rc); + } else perror_msg("'%s'->'%s'", dev, dir); + + break; } if (fp) fclose(fp); - - if (rc) perror_msg("'%s' on '%s'", dev, dir); } void mount_main(void) @@ -261,8 +261,9 @@ void mount_main(void) // Do we need to do an /etc/fstab trawl? // This covers -a, -o remount, one argument, all user mounts - if ((toys.optflags & FLAG_a) || remount || !dir || getuid()) { + if ((toys.optflags & FLAG_a) || (dev && (!dir || getuid() || remount))) { if (!remount) mtl = xgetmountlist("/etc/fstab"); + for (mm = remount ? remount : mtl; mm; mm = (remount ? mm->prev : mm->next)) { int aflags, noauto, len; -- cgit v1.2.3