diff options
Diffstat (limited to 'util-linux/mount.c')
-rw-r--r-- | util-linux/mount.c | 681 |
1 files changed, 292 insertions, 389 deletions
diff --git a/util-linux/mount.c b/util-linux/mount.c index b059d70..924d79d 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -4,6 +4,7 @@ * * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 2005 by Rob Landley <rob@landley.net> * * 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 @@ -19,29 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * 3/21/1999 Charles P. Wright <cpwright@cpwright.com> - * searches through fstab when -a is passed - * will try mounting stuff with all fses when passed -t auto - * - * 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab. - * - * 1999-10-07 Erik Andersen <andersen@codepoet.org>. - * Rewrite of a lot of code. Removed mtab usage (I plan on - * putting it back as a compile-time option some time), - * major adjustments to option parsing, and some serious - * dieting all around. - * - * 1999-11-06 mtab support is back - andersee - * - * 2000-01-12 Ben Collins <bcollins@debian.org>, Borrowed utils-linux's - * mount to add loop support. - * - * 2000-04-30 Dave Cinege <dcinege@psychosis.com> - * Rewrote fstab while loop and lower mount section. Can now do - * single mounts from fstab. Can override fstab options for single - * mount. Common mount_one call for single mounts and 'all'. Fixed - * mtab updating and stale entries. Removed 'remount' default. - * */ #include <limits.h> @@ -52,351 +30,131 @@ #include <stdio.h> #include <mntent.h> #include <ctype.h> +#include <sys/mount.h> +#include <fcntl.h> // for CONFIG_FEATURE_MOUNT_LOOP +#include <sys/ioctl.h> // for CONFIG_FEATURE_MOUNT_LOOP #include "busybox.h" -#ifdef CONFIG_NFSMOUNT -#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) +/* This is just a warning of a common mistake. Possibly this should be a + * uclibc faq entry rather than in busybox... */ +#if ENABLE_NFSMOUNT && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) #error "You need to build uClibc with UCLIBC_HAS_RPC for busybox mount with NFS support to compile." #endif -#endif - -enum { - MS_MGC_VAL = 0xc0ed0000, /* Magic number indicatng "new" flags */ - MS_RDONLY = 1, /* Mount read-only */ - MS_NOSUID = 2, /* Ignore suid and sgid bits */ - MS_NODEV = 4, /* Disallow access to device special files */ - MS_NOEXEC = 8, /* Disallow program execution */ - MS_SYNCHRONOUS = 16, /* Writes are synced at once */ - MS_REMOUNT = 32, /* Alter flags of a mounted FS */ - MS_MANDLOCK = 64, /* Allow mandatory locks on an FS */ - S_QUOTA = 128, /* Quota initialized for file/directory/symlink */ - S_APPEND = 256, /* Append-only file */ - S_IMMUTABLE = 512, /* Immutable file */ - MS_NOATIME = 1024, /* Do not update access times. */ - MS_NODIRATIME = 2048, /* Do not update directory access times */ - MS_BIND = 4096, /* Use the new linux 2.4.x "mount --bind" feature */ - MS_MOVE = 8192, /* Use the new linux 2.4.x "mount --move" feature */ -}; - -#if defined CONFIG_FEATURE_MOUNT_LOOP -#include <fcntl.h> -#include <sys/ioctl.h> -static int use_loop = FALSE; +// These two aren't always defined in old headers +#ifndef MS_BIND +#define MS_BIND 4096 +#endif +#ifndef MS_MOVE +#define MS_MOVE 8192 #endif -extern int mount(__const char *__special_file, __const char *__dir, - __const char *__fstype, unsigned long int __rwflag, - __const void *__data); -extern int umount(__const char *__special_file); -extern int umount2(__const char *__special_file, int __flags); - -extern int sysfs(int option, unsigned int fs_index, char *buf); +/* Consume standard mount options (from -o options or --options). + * Set appropriate flags and collect unrecognized ones as a comma separated + * string to pass to kernel */ -struct mount_options { +struct { const char *name; - unsigned long and; - unsigned long or; + long flags; +} static const mount_options[] = { + {"loop", 0}, + {"defaults", 0}, + {"noauto", 0}, + {"ro", MS_RDONLY}, + {"rw", ~MS_RDONLY}, + {"nosuid", MS_NOSUID}, + {"suid", ~MS_NOSUID}, + {"dev", ~MS_NODEV}, + {"nodev", MS_NODEV}, + {"exec", ~MS_NOEXEC}, + {"noexec", MS_NOEXEC}, + {"sync", MS_SYNCHRONOUS}, + {"async", ~MS_SYNCHRONOUS}, + {"remount", MS_REMOUNT}, + {"atime", MS_NOATIME}, + {"noatime", MS_NOATIME}, + {"diratime", MS_NODIRATIME}, + {"nodiratime", MS_NODIRATIME}, + {"bind", MS_BIND}, + {"move", MS_MOVE} }; -static const struct mount_options mount_options[] = { - {"async", ~MS_SYNCHRONOUS, 0}, - {"atime", ~0, ~MS_NOATIME}, - {"defaults", ~0, 0}, - {"noauto", ~0, 0}, - {"dev", ~MS_NODEV, 0}, - {"diratime", ~0, ~MS_NODIRATIME}, - {"exec", ~MS_NOEXEC, 0}, - {"noatime", ~0, MS_NOATIME}, - {"nodev", ~0, MS_NODEV}, - {"nodiratime", ~0, MS_NODIRATIME}, - {"noexec", ~0, MS_NOEXEC}, - {"nosuid", ~0, MS_NOSUID}, - {"remount", ~0, MS_REMOUNT}, - {"ro", ~0, MS_RDONLY}, - {"rw", ~MS_RDONLY, 0}, - {"suid", ~MS_NOSUID, 0}, - {"sync", ~0, MS_SYNCHRONOUS}, - {"bind", ~0, MS_BIND}, - {"move", ~0, MS_MOVE}, - {0, 0, 0} -}; - -static int -do_mount(char *specialfile, char *dir, char *filesystemtype, long flags, - void *string_flags, int useMtab, int fakeIt, char *mtab_opts, - int mount_all) -{ - int status = 0; - -#if defined CONFIG_FEATURE_MOUNT_LOOP - char *lofile = NULL; -#endif - - if (!fakeIt) { -#if defined CONFIG_FEATURE_MOUNT_LOOP - if (use_loop == TRUE) { - int loro = flags & MS_RDONLY; - - lofile = specialfile; - - specialfile = find_unused_loop_device(); - if (specialfile == NULL) { - bb_error_msg_and_die("Could not find a spare loop device"); - } - if (set_loop(specialfile, lofile, 0, &loro)) { - bb_error_msg_and_die("Could not setup loop device"); - } - if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ - bb_error_msg("WARNING: loop device is read-only"); - flags |= MS_RDONLY; - } - } -#endif - status = mount(specialfile, dir, filesystemtype, flags, string_flags); - if (status < 0 && errno == EROFS) { - bb_error_msg("%s is write-protected, mounting read-only", - specialfile); - status = mount(specialfile, dir, filesystemtype, flags |= - MS_RDONLY, string_flags); - } - /* Don't whine about already mounted filesystems when mounting all. */ - if (status < 0 && errno == EBUSY && mount_all) { - return TRUE; - } - } - - - /* If the mount was sucessful, do anything needed, then return TRUE */ - if (status == 0 || fakeIt == TRUE) { - -#if defined CONFIG_FEATURE_MTAB_SUPPORT - if (useMtab) { - erase_mtab(specialfile); /* Clean any stale entries */ - write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); - } -#endif - return (TRUE); - } - - /* Bummer. mount failed. Clean up */ -#if defined CONFIG_FEATURE_MOUNT_LOOP - if (lofile != NULL) { - del_loop(specialfile); - } -#endif - - if (errno == EPERM) { - bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); - } - - return (FALSE); -} - - -static void paste_str(char **s1, const char *s2) -{ - *s1 = xrealloc(*s1, strlen(*s1) + strlen(s2) + 1); - strcat(*s1, s2); -} - -/* Seperate standard mount options from the nonstandard string options */ +/* Uses the mount_options list above */ static void parse_mount_options(char *options, int *flags, char **strflags) { - while (options) { - int gotone = FALSE; + // Loop through options + for(;;) { + int i; char *comma = strchr(options, ','); - const struct mount_options *f = mount_options; - if (comma) { - *comma = '\0'; - } - - while (f->name != 0) { - if (strcasecmp(f->name, options) == 0) { + if(comma) *comma = 0; - *flags &= f->and; - *flags |= f->or; - gotone = TRUE; + // Find this option in mount_options + for(i = 0; i < (sizeof(mount_options) / sizeof(*mount_options)); i++) { + if(!strcasecmp(mount_options[i].name, options)) { + long fl = mount_options[i].flags; + if(fl < 0) *flags &= fl; + else *flags |= fl; break; } - f++; - } -#if defined CONFIG_FEATURE_MOUNT_LOOP - if (!strcasecmp("loop", options)) { /* loop device support */ - use_loop = TRUE; - gotone = TRUE; } -#endif - if (!gotone) { - if (**strflags) { - /* have previous parsed options */ - paste_str(strflags, ","); - } - paste_str(strflags, options); + // Unrecognized mount option? + if(i == sizeof(mount_options)) { + // Add it to strflags, to pass on to kernel + i = *strflags ? strlen(*strflags) : 0; + *strflags = xrealloc(*strflags, i+strlen(options)+2); + // Comma separated if it's not the first one + if(i) (*strflags)[i] = ','; + strcpy((*strflags)+i, options); } - if (comma) { + // Advance to next option, or finish + if(comma) { *comma = ','; options = ++comma; - } else { - break; - } + } else break; } } -static int mount_one(char *blockDevice, char *directory, char *filesystemType, - unsigned long flags, char *string_flags, int useMtab, - int fakeIt, char *mtab_opts, int whineOnErrors, - int mount_all) -{ - int status = 0; - if (strcmp(filesystemType, "auto") == 0) { - char buf[255]; - FILE *f; - int read_proc = 0; - - f = fopen("/etc/filesystems", "r"); - - if (f) { - while (fgets(buf, sizeof(buf), f)) { - if (*buf == '*') { - read_proc = 1; - } else if (*buf == '#') { - continue; - } else { - filesystemType = buf; - - /* Add NULL termination to each line */ - while (*filesystemType && !isspace(*filesystemType)) { - filesystemType++; - } - *filesystemType = '\0'; - - filesystemType = buf; - - if (bb_strlen(filesystemType)) { - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, - useMtab, fakeIt, mtab_opts, mount_all); - if (status) { - break; - } - } - - } - } - fclose(f); - } else { - read_proc = 1; - } - - if (read_proc && !status) { - - f = bb_xfopen("/proc/filesystems", "r"); +/* This does the work */ - while (fgets(buf, sizeof(buf), f) != NULL) { - filesystemType = buf; - if (*filesystemType == '\t') { /* Not a nodev filesystem */ - - /* Add NULL termination to each line */ - while (*filesystemType && *filesystemType != '\n') { - filesystemType++; - } - *filesystemType = '\0'; - - filesystemType = buf; - filesystemType++; /* hop past tab */ - - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, useMtab, - fakeIt, mtab_opts, mount_all); - if (status) { - break; - } - } - } - fclose(f); - } - } else { - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, useMtab, fakeIt, - mtab_opts, mount_all); - } - - if (!status) { - if (whineOnErrors) { - bb_perror_msg("Mounting %s on %s failed", blockDevice, directory); - } - return (FALSE); - } - return (TRUE); -} - -static void show_mounts(char *onlytype) +extern int mount_main(int argc, char **argv) { - FILE *mountTable = setmntent(bb_path_mtab_file, "r"); - - if (mountTable) { - struct mntent *m; + char *string_flags = 0, *fsType = 0, *blockDevice = 0, *directory = 0, + *loopFile = 0, *buf = 0, + *files[] = {"/etc/filesystems", "/proc/filesystems", 0}; + int i, opt, all = FALSE, fakeIt = FALSE, allowWrite = FALSE, + rc = EXIT_FAILURE, useMtab = ENABLE_FEATURE_MTAB_SUPPORT; + int flags=0xc0ed0000; // Needed for linux 2.2, ignored by 2.4 and 2.6. + FILE *file = 0,*f = 0; + char path[PATH_MAX*2]; + struct mntent m; + struct stat statbuf; - while ((m = getmntent(mountTable)) != 0) { - char *blockDevice = m->mnt_fsname; + /* parse long options, like --bind and --move. Note that -o option + * and --option are synonymous. Yes, this means --remount,rw works. */ - if (strcmp(blockDevice, "rootfs") == 0) { - continue; - } else if (strcmp(blockDevice, "/dev/root") == 0) { - blockDevice = find_real_root_device_name(); - } - if (!onlytype || (strcmp(m->mnt_type, onlytype) == 0)) { - printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, - m->mnt_type, m->mnt_opts); - } -#ifdef CONFIG_FEATURE_CLEAN_UP - if (blockDevice != m->mnt_fsname) { - free(blockDevice); - } -#endif - } - endmntent(mountTable); - } else { - bb_perror_msg_and_die(bb_path_mtab_file); + for(i = opt = 0; i < argc; i++) { + if(argv[i][0] == '-' && argv[i][1] == '-') + parse_mount_options(argv[i]+2, &flags, &string_flags); + else argv[opt++] = argv[i]; } - exit(EXIT_SUCCESS); -} + argc = opt; -extern int mount_main(int argc, char **argv) -{ - struct stat statbuf; - char *string_flags = bb_xstrdup(""); - char *extra_opts; - int flags = 0; - char *filesystemType = "auto"; - int got_filesystemType = 0; - char *device = xmalloc(PATH_MAX); - char *directory = xmalloc(PATH_MAX); - struct mntent *m = NULL; - int all = FALSE; - int fakeIt = FALSE; - int useMtab = TRUE; - int rc = EXIT_FAILURE; - FILE *f = 0; - int opt; - - /* Parse options */ - while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) { + // Parse remaining options + + while((opt = getopt(argc, argv, "o:t:rwafnv")) > 0) { switch (opt) { case 'o': parse_mount_options(optarg, &flags, &string_flags); break; + case 't': + fsType = optarg; + break; case 'r': flags |= MS_RDONLY; break; - case 't': - filesystemType = optarg; - got_filesystemType = 1; - break; case 'w': - flags &= ~MS_RDONLY; + allowWrite=TRUE; break; case 'a': all = TRUE; @@ -405,93 +163,238 @@ extern int mount_main(int argc, char **argv) fakeIt = TRUE; break; case 'n': -#ifdef CONFIG_FEATURE_MTAB_SUPPORT useMtab = FALSE; -#endif break; case 'v': - break; /* ignore -v */ + break; // ignore -v + default: + bb_show_usage(); } } - if (!all && (optind == argc)) { - show_mounts(got_filesystemType ? filesystemType : NULL); - } + // If we have no arguments, show currently mounted filesystems - if (optind < argc) { - /* if device is a filename get its real path */ - if (stat(argv[optind], &statbuf) == 0) { - char *tmp = bb_simplify_path(argv[optind]); + if(!all && (optind == argc)) { + FILE *mountTable = setmntent(bb_path_mtab_file, "r"); - safe_strncpy(device, tmp, PATH_MAX); - } else { - safe_strncpy(device, argv[optind], PATH_MAX); + if(!mountTable) bb_perror_msg_and_die(bb_path_mtab_file); + + while (getmntent_r(mountTable,&m,path,sizeof(path))) { + blockDevice = m.mnt_fsname; + + // Clean up display a little bit regarding root devie + if(!strcmp(blockDevice, "rootfs")) continue; + if(!strcmp(blockDevice, "/dev/root")) + blockDevice = find_block_device("/"); + + if(!fsType || !strcmp(m.mnt_type, fsType)) + printf("%s on %s type %s (%s)\n", blockDevice, m.mnt_dir, + m.mnt_type, m.mnt_opts); + if(ENABLE_FEATURE_CLEAN_UP && blockDevice != m.mnt_fsname) + free(blockDevice); } + endmntent(mountTable); + return EXIT_SUCCESS; } - if (optind + 1 < argc) - directory = bb_simplify_path(argv[optind + 1]); + /* The next argument is what to mount. if there's an argument after that + * it's where to mount it. If we're not mounting all, and we have both + * of these arguments, jump straight to the actual mount. */ + + statbuf.st_mode=0; + if(optind < argc) + blockDevice = !stat(argv[optind], &statbuf) ? + bb_simplify_path(argv[optind]) : + (ENABLE_FEATURE_CLEAN_UP ? strdup(argv[optind]) : argv[optind]); + if(optind+1 < argc) directory = bb_simplify_path(argv[optind+1]); + + // If we don't have to loop through fstab, skip ahead a bit. + + if(!all && optind+1!=argc) goto singlemount; + + // Loop through /etc/fstab entries to look up this entry. - if (all || optind + 1 == argc) { - f = setmntent("/etc/fstab", "r"); + if(!(file=setmntent("/etc/fstab","r"))) + bb_perror_msg_and_die("\nCannot read /etc/fstab"); + for(;;) { - if (f == NULL) - bb_perror_msg_and_die("\nCannot read /etc/fstab"); + // Get next fstab entry - while ((m = getmntent(f)) != NULL) { - if (!all && (optind + 1 == argc) - && ((strcmp(device, m->mnt_fsname) != 0) - && (strcmp(device, m->mnt_dir) != 0))) { + if(!getmntent_r(file,&m,path,sizeof(path))) { + if(!all) + bb_perror_msg("Can't find %s in /etc/fstab\n", blockDevice); + break; + } + + // If we're mounting all and all doesn't mount this one, skip it. + + if(all) { + if(strstr(m.mnt_opts,"noauto") || strstr(m.mnt_type,"swap")) continue; + flags=0; + + /* If we're mounting something specific and this isn't it, skip it. + * Note we must match both the exact text in fstab (ala "proc") or + * a full path from root */ + + } else if(strcmp(blockDevice,m.mnt_fsname) && + strcmp(argv[optind],m.mnt_fsname) && + strcmp(blockDevice,m.mnt_dir) && + strcmp(argv[optind],m.mnt_dir)) continue; + + /* Parse flags from /etc/fstab (unless this is a single mount + * overriding fstab -- note the "all" test above zeroed the flags, + * to prevent flags from previous entries affecting this one, so + * the only way we could get here with nonzero flags is a single + * mount). */ + + if(!flags) { + if(ENABLE_FEATURE_CLEAN_UP) free(string_flags); + string_flags=NULL; + parse_mount_options(m.mnt_opts, &flags, &string_flags); + } + + /* Fill out remaining fields with info from mtab */ + + if(ENABLE_FEATURE_CLEAN_UP) { + free(blockDevice); + blockDevice=strdup(m.mnt_fsname); + free(directory); + directory=strdup(m.mnt_type); + } else { + blockDevice=m.mnt_fsname; + directory=m.mnt_dir; + } + fsType=m.mnt_type; + + /* Ok, we're ready to actually mount a specific source on a specific + * directory now. */ + +singlemount: + + // If they said -w, override fstab + + if(allowWrite) flags&=~MS_RDONLY; + + // Might this be an NFS filesystem? + + if(ENABLE_NFSMOUNT && (!fsType || !strcmp(fsType,"nfs")) && + strchr(blockDevice, ':') != NULL) + { + if(nfsmount(blockDevice, directory, &flags, &string_flags, 1)) + bb_perror_msg("nfsmount failed"); + else { + rc=EXIT_SUCCESS; + fsType="nfs"; } + } else { + + // Do we need to allocate a loopback device? - if (all && ( /* If we're mounting 'all' */ - (strstr(m->mnt_opts, "noauto")) || /* and the file system isn't noauto, */ - (strstr(m->mnt_type, "swap")))) /* and isn't swap, then mount it */ + if(ENABLE_FEATURE_MOUNT_LOOP && !fakeIt && S_ISREG(statbuf.st_mode)) { - continue; + loopFile = blockDevice; + blockDevice = 0; + switch(set_loop(&blockDevice, loopFile, 0)) { + case 0: + case 1: + break; + default: + bb_error_msg_and_die( + errno == EPERM || errno == EACCES ? + bb_msg_perm_denied_are_you_root : + "Couldn't setup loop device"); + break; + } } - if (all || flags == 0) { /* Allow single mount to override fstab flags */ - flags = 0; - string_flags[0] = 0; - parse_mount_options(m->mnt_opts, &flags, &string_flags); - } + /* If we know the fstype (or don't need to), jump straight + * to the actual mount. */ - strcpy(device, m->mnt_fsname); - strcpy(directory, m->mnt_dir); - filesystemType = bb_xstrdup(m->mnt_type); - singlemount: - extra_opts = string_flags; - rc = EXIT_SUCCESS; -#ifdef CONFIG_NFSMOUNT - if (strchr(device, ':') != NULL) { - filesystemType = "nfs"; - if (nfsmount - (device, directory, &flags, &extra_opts, &string_flags, - 1)) { - bb_perror_msg("nfsmount failed"); - rc = EXIT_FAILURE; + if(fsType || (flags & (MS_REMOUNT | MS_BIND | MS_MOVE))) + goto mount_it_now; + } + + // Loop through filesystem types until mount succeeds or we run out + + for(i = 0; files[i] && rc; i++) { + f = fopen(files[i], "r"); + if(!f) continue; + // Get next block device backed filesystem + for(buf = 0; (buf = fsType = bb_get_chomped_line_from_file(f)); + free(buf)) + { + // Skip funky entries in /proc + if(!strncmp(buf,"nodev",5) && isspace(buf[5])) continue; + + while(isspace(*fsType)) fsType++; + if(*buf=='#' || *buf=='*') continue; + if(!*fsType) continue; +mount_it_now: + // Okay, try to mount + + if (!fakeIt) { + for(;;) { + rc = mount(blockDevice, directory, fsType, flags, string_flags); + if(!rc || (flags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS)) + break; + bb_error_msg("%s is write-protected, mounting read-only", blockDevice); + flags|=MS_RDONLY; + } } + if(!rc) break; } -#endif - if (!mount_one - (device, directory, filesystemType, flags, string_flags, - useMtab, fakeIt, extra_opts, TRUE, all)) { - rc = EXIT_FAILURE; + if(f) fclose(f); + if(!f || !rc) break; + } + + /* If the mount was sucessful, and we're maintaining an old-style + * mtab file by hand, add new entry to it now. */ + if((!rc || fakeIt) && useMtab) { + FILE *mountTable = setmntent(bb_path_mtab_file, "a+"); + + if(!mountTable) bb_perror_msg(bb_path_mtab_file); + else { + // Remove trailing / (if any) from directory we mounted on + int length=strlen(directory); + if(length>1 && directory[length-1] == '/') + directory[length-1]=0; + + // Fill out structure (should be ok to re-use existing one). + m.mnt_fsname=blockDevice; + m.mnt_dir=directory; + m.mnt_type=fsType ? : "--bind"; + m.mnt_opts=string_flags ? : + ((flags & MS_RDONLY) ? "ro" : "rw"); + m.mnt_freq = 0; + m.mnt_passno = 0; + + // Write and close + addmntent(mountTable, &m); + endmntent(mountTable); } - if (!all) { - break; + } else { + // Mount failed. Clean up + if(loopFile) { + del_loop(blockDevice); + if(ENABLE_FEATURE_CLEAN_UP) free(loopFile); } + // Don't whine about already mounted fs when mounting all. + if(rc<0 && errno == EBUSY && all) rc=0; + else if (errno == EPERM) + bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); } - if (f) { - endmntent(f); + // We couldn't free this earlier becase fsType could be in buf. + if(ENABLE_FEATURE_CLEAN_UP) { + free(buf); + free(blockDevice); + free(directory); } - if (!all && f && m == NULL) { - fprintf(stderr, "Can't find %s in /etc/fstab\n", device); - } - return rc; + if(!all) break; } - goto singlemount; + if(file) endmntent(file); + if(rc) bb_perror_msg("Mounting %s on %s failed", blockDevice, directory); + + return rc ? : EXIT_FAILURE; } |