X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=mount.c;h=e40d75f794856e9ae1059526e0eb555729f1f821;hb=0a4f578fdc867714e8e942add8700aa15bd80443;hp=bde55d155f99ab6cecb68edee7679131e5bab197;hpb=7ab9c7ee52db8759d457819f5480378fa3aa97cc;p=oweals%2Fbusybox.git diff --git a/mount.c b/mount.c index bde55d155..e40d75f79 100644 --- a/mount.c +++ b/mount.c @@ -34,67 +34,61 @@ * * 2000-01-12 Ben Collins , Borrowed utils-linux's * mount to add loop support. + * + * 2000-04-30 Dave Cinege + * 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 "internal.h" +#include #include #include #include #include #include #include -#include #include +#include "busybox.h" #if defined BB_FEATURE_USE_DEVPS_PATCH -#include -#endif -#ifndef MS_RDONLY -#include +# include /* For Erik's nifty devmtab device driver */ #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 */ +}; + #if defined BB_FEATURE_MOUNT_LOOP #include #include -#include - - static int use_loop = FALSE; #endif -extern const char mtab_file[]; /* Defined in utility.c */ +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); -static const char mount_usage[] = - "mount [flags] device directory [-o options,more-options]\n" -#ifndef BB_FEATURE_TRIVIAL_HELP - "\nMount a filesystem\n\n" - "Flags:\n" - "\t-a:\t\tMount all filesystems in fstab.\n" -#ifdef BB_MTAB - "\t-f:\t\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" - "\t-n:\t\tDon't write a mount table entry.\n" -#endif - "\t-o option:\tOne of many filesystem options, listed below.\n" - "\t-r:\t\tMount the filesystem read-only.\n" - "\t-t fs-type:\tSpecify the filesystem type.\n" - "\t-w:\t\tMount for reading and writing (default).\n" - "\n" - "Options for use with the \"-o\" flag:\n" - "\tasync/sync:\tWrites are asynchronous / synchronous.\n" - "\tatime/noatime:\tEnable / disable updates to inode access times.\n" - "\tdev/nodev:\tAllow use of special device files / disallow them.\n" - "\texec/noexec:\tAllow use of executable files / disallow them.\n" -#if defined BB_FEATURE_MOUNT_LOOP - "\tloop:\t\tMounts a file via loop device.\n" -#endif - "\tsuid/nosuid:\tAllow set-user-id-root programs / disallow them.\n" - "\tremount:\tRe-mount a currently-mounted filesystem, changing its flags.\n" - "\tro/rw:\t\tMount for read-only / read-write.\n" - "\nThere are EVEN MORE flags that are specific to each filesystem.\n" - "You'll have to see the written documentation for those.\n" -#endif - ; +extern int sysfs( int option, unsigned int fs_index, char * buf); +extern const char mtab_file[]; /* Defined in utility.c */ struct mount_options { const char *name; @@ -119,6 +113,7 @@ static const struct mount_options mount_options[] = { {"rw", ~MS_RDONLY, 0}, {"suid", ~MS_NOSUID, 0}, {"sync", ~0, MS_SYNCHRONOUS}, + {"bind", ~0, MS_BIND}, {0, 0, 0} }; @@ -128,42 +123,45 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, char *mtab_opts) { int status = 0; +#if defined BB_FEATURE_MOUNT_LOOP char *lofile = NULL; +#endif -#if defined BB_MTAB if (fakeIt == FALSE) -#endif { #if defined BB_FEATURE_MOUNT_LOOP if (use_loop==TRUE) { int loro = flags & MS_RDONLY; - char *lofile = specialfile; + + lofile = specialfile; specialfile = find_unused_loop_device(); if (specialfile == NULL) { - fprintf(stderr, "Could not find a spare loop device\n"); - return (FALSE); + error_msg_and_die("Could not find a spare loop device"); } if (set_loop(specialfile, lofile, 0, &loro)) { - fprintf(stderr, "Could not setup loop device\n"); - return (FALSE); + error_msg_and_die("Could not setup loop device"); } if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ - fprintf(stderr, "WARNING: loop device is read-only\n"); + error_msg("WARNING: loop device is read-only"); flags &= ~MS_RDONLY; } } #endif - status = - mount(specialfile, dir, filesystemtype, flags, string_flags); + status = mount(specialfile, dir, filesystemtype, flags, string_flags); + if (errno == EROFS) { + error_msg("%s is write-protected, mounting read-only", specialfile); + status = mount(specialfile, dir, filesystemtype, flags |= MS_RDONLY, string_flags); + } } /* If the mount was sucessful, do anything needed, then return TRUE */ - if (status == 0) { + if (status == 0 || fakeIt==TRUE) { -#if defined BB_MTAB +#if defined BB_FEATURE_MTAB_SUPPORT if (useMtab == TRUE) { + erase_mtab(specialfile); // Clean any stale entries write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); } #endif @@ -176,6 +174,11 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, del_loop(specialfile); } #endif + + if (errno == EPERM) { + error_msg_and_die("permission denied. Are you root?"); + } + return (FALSE); } @@ -183,7 +186,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, /* Seperate standard mount options from the nonstandard string options */ static void -parse_mount_options(char *options, unsigned long *flags, char *strflags) +parse_mount_options(char *options, int *flags, char *strflags) { while (options) { int gotone = FALSE; @@ -227,278 +230,240 @@ parse_mount_options(char *options, unsigned long *flags, char *strflags) } } -int +extern 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 status = 0; -#if defined BB_FEATURE_USE_PROCFS - char buf[255]; if (strcmp(filesystemType, "auto") == 0) { - FILE *f = fopen("/proc/filesystems", "r"); - - if (f == NULL) - return (FALSE); - - 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 - + static const char *noauto_array[] = { "tmpfs", "shm", "proc", "ramfs", "devpts", "devfs", 0 }; + const char **noauto_fstype; + const int num_of_filesystems = sysfs(3, 0, 0); + char buf[255]; + int i=0; + + filesystemType=buf; + + while(i < num_of_filesystems) { + sysfs(2, i++, filesystemType); + for (noauto_fstype = noauto_array; *noauto_fstype; noauto_fstype++) { + if (!strcmp(filesystemType, *noauto_fstype)) { + break; + } + } + if (!*noauto_fstype) { status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, - useMtab, fakeIt, mtab_opts); + flags | MS_MGC_VAL, string_flags, + useMtab, fakeIt, mtab_opts); if (status == TRUE) break; } } - fclose(f); - } else -#endif -#if defined BB_FEATURE_USE_DEVPS_PATCH - if (strcmp(filesystemType, "auto") == 0) { - int fd, i, numfilesystems; - char device[] = "/dev/mtab"; - struct k_fstype *fslist; - - /* open device */ - fd = open(device, O_RDONLY); - if (fd < 0) - fatalError("open failed for `%s': %s\n", device, strerror (errno)); - - /* How many filesystems? We need to know to allocate enough space */ - numfilesystems = ioctl (fd, DEVMTAB_COUNT_FILESYSTEMS); - if (numfilesystems<0) - fatalError("\nDEVMTAB_COUNT_FILESYSTEMS: %s\n", strerror (errno)); - fslist = (struct k_fstype *) calloc ( numfilesystems, sizeof(struct k_fstype)); - - /* Grab the list of available filesystems */ - status = ioctl (fd, DEVMTAB_GET_FILESYSTEMS, fslist); - if (status<0) - fatalError("\nDEVMTAB_GET_FILESYSTEMS: %s\n", strerror (errno)); - - /* Walk the list trying to mount filesystems - * that do not claim to be nodev filesystems */ - for( i = 0 ; i < numfilesystems ; i++) { - if (fslist[i].mnt_nodev) - continue; - status = do_mount(blockDevice, directory, fslist[i].mnt_type, - flags | MS_MGC_VAL, string_flags, - useMtab, fakeIt, mtab_opts); - if (status == TRUE) - break; - } - free( fslist); - close(fd); - } else -#endif - { + } else { status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, useMtab, - fakeIt, mtab_opts); + flags | MS_MGC_VAL, string_flags, useMtab, + fakeIt, mtab_opts); } - if (status == FALSE && whineOnErrors == TRUE) { + if (status == FALSE) { if (whineOnErrors == TRUE) { - fprintf(stderr, "Mounting %s on %s failed: %s\n", - blockDevice, directory, strerror(errno)); + perror_msg("Mounting %s on %s failed", blockDevice, directory); } return (FALSE); } return (TRUE); } +void show_mounts() +{ +#if defined BB_FEATURE_USE_DEVPS_PATCH + int fd, i, numfilesystems; + char device[] = "/dev/mtab"; + struct k_mntent *mntentlist; + + /* open device */ + fd = open(device, O_RDONLY); + if (fd < 0) + perror_msg_and_die("open failed for `%s'", device); + + /* How many mounted filesystems? We need to know to + * allocate enough space for later... */ + numfilesystems = ioctl (fd, DEVMTAB_COUNT_MOUNTS); + if (numfilesystems<0) + perror_msg_and_die( "\nDEVMTAB_COUNT_MOUNTS"); + mntentlist = (struct k_mntent *) xcalloc ( numfilesystems, sizeof(struct k_mntent)); + + /* Grab the list of mounted filesystems */ + if (ioctl (fd, DEVMTAB_GET_MOUNTS, mntentlist)<0) + perror_msg_and_die( "\nDEVMTAB_GET_MOUNTS"); + + for( i = 0 ; i < numfilesystems ; i++) { + printf( "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname, + mntentlist[i].mnt_dir, mntentlist[i].mnt_type, + mntentlist[i].mnt_opts, mntentlist[i].mnt_freq, + mntentlist[i].mnt_passno); + } +#ifdef BB_FEATURE_CLEAN_UP + /* Don't bother to close files or free memory. Exit + * does that automagically, so we can save a few bytes */ + free( mntentlist); + close(fd); +#endif + exit(EXIT_SUCCESS); +#else + FILE *mountTable = setmntent(mtab_file, "r"); + + if (mountTable) { + struct mntent *m; + + while ((m = getmntent(mountTable)) != 0) { + char *blockDevice = m->mnt_fsname; + if (strcmp(blockDevice, "/dev/root") == 0) { + blockDevice = find_real_root_device_name(blockDevice); + } + printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, + m->mnt_type, m->mnt_opts); +#ifdef BB_FEATURE_CLEAN_UP + if(blockDevice != m->mnt_fsname) + free(blockDevice); +#endif + } + endmntent(mountTable); + } else { + perror_msg_and_die("%s", mtab_file); + } + exit(EXIT_SUCCESS); +#endif +} + extern int mount_main(int argc, char **argv) { + struct stat statbuf; char string_flags_buf[1024] = ""; char *string_flags = string_flags_buf; char *extra_opts = string_flags_buf; - unsigned long flags = 0; + int flags = 0; char *filesystemType = "auto"; - char *device = NULL; - char *directory = NULL; + char *device = xmalloc(PATH_MAX); + char *directory = xmalloc(PATH_MAX); int all = FALSE; int fakeIt = FALSE; int useMtab = TRUE; - int i; + int rc = EXIT_FAILURE; + int fstabmount = FALSE; + int opt; -#if defined BB_FEATURE_USE_DEVPS_PATCH - if (argc == 1) { - int fd, i, numfilesystems; - char device[] = "/dev/mtab"; - struct k_mntent *mntentlist; - - /* open device */ - fd = open(device, O_RDONLY); - if (fd < 0) - fatalError("open failed for `%s': %s\n", device, strerror (errno)); - - /* How many mounted filesystems? We need to know to - * allocate enough space for later... */ - numfilesystems = ioctl (fd, DEVMTAB_COUNT_MOUNTS); - if (numfilesystems<0) - fatalError( "\nDEVMTAB_COUNT_MOUNTS: %s\n", strerror (errno)); - mntentlist = (struct k_mntent *) calloc ( numfilesystems, sizeof(struct k_mntent)); - - /* Grab the list of mounted filesystems */ - if (ioctl (fd, DEVMTAB_GET_MOUNTS, mntentlist)<0) - fatalError( "\nDEVMTAB_GET_MOUNTS: %s\n", strerror (errno)); - - for( i = 0 ; i < numfilesystems ; i++) { - fprintf( stdout, "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname, - mntentlist[i].mnt_dir, mntentlist[i].mnt_type, - mntentlist[i].mnt_opts, mntentlist[i].mnt_freq, - mntentlist[i].mnt_passno); - } - /* Don't bother to close files or free memory. Exit - * does that automagically, so we can save a few bytes */ -#if 0 - free( mntentlist); - close(fd); + /* Parse options */ + while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) { + switch (opt) { + case 'o': + parse_mount_options(optarg, &flags, string_flags); + break; + case 'r': + flags |= MS_RDONLY; + break; + case 't': + filesystemType = optarg; + break; + case 'w': + flags &= ~MS_RDONLY; + break; + case 'a': + all = TRUE; + break; + case 'f': + fakeIt = TRUE; + break; +#ifdef BB_FEATURE_MTAB_SUPPORT + case 'n': + useMtab = FALSE; + break; #endif - exit(TRUE); + case 'v': + break; /* ignore -v */ + } } -#else - if (argc == 1) { - FILE *mountTable = setmntent(mtab_file, "r"); - if (mountTable) { - struct mntent *m; + if (!all && optind == argc) + show_mounts(); - while ((m = getmntent(mountTable)) != 0) { - char *blockDevice = m->mnt_fsname; - if (strcmp(blockDevice, "/dev/root") == 0) { - find_real_root_device_name( blockDevice); - } - printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, - m->mnt_type, m->mnt_opts); - } - endmntent(mountTable); + if (optind < argc) { + /* if device is a filename get its real path */ + if (stat(argv[optind], &statbuf) == 0) { + realpath(argv[optind], device); } else { - perror(mtab_file); + safe_strncpy(device, argv[optind], PATH_MAX); } - exit(TRUE); } -#endif - /* Parse options */ - i = --argc; - argv++; - while (i > 0 && **argv) { - if (**argv == '-') { - char *opt = *argv; - - while (i > 0 && *++opt) - switch (*opt) { - case 'o': - if (--i == 0) { - goto goodbye; - } - parse_mount_options(*(++argv), &flags, string_flags); - break; - case 'r': - flags |= MS_RDONLY; - break; - case 't': - if (--i == 0) { - goto goodbye; - } - filesystemType = *(++argv); - break; - case 'w': - flags &= ~MS_RDONLY; - break; - case 'a': - all = TRUE; - break; - case 'f': - fakeIt = TRUE; - break; -#ifdef BB_MTAB - case 'n': - useMtab = FALSE; - break; -#endif - case 'v': - break; /* ignore -v */ - case 'h': - case '-': - goto goodbye; - } - } else { - if (device == NULL) - device = *argv; - else if (directory == NULL) - directory = *argv; - else { - goto goodbye; - } + if (optind + 1 < argc) { + if (realpath(argv[optind + 1], directory) == NULL) { + perror_msg_and_die("%s", directory); } - i--; - argv++; } - - if (all == TRUE) { - struct mntent *m; + + if (all == TRUE || optind + 1 == argc) { + struct mntent *m = NULL; FILE *f = setmntent("/etc/fstab", "r"); + fstabmount = TRUE; if (f == NULL) - fatalError( "\nCannot read /etc/fstab: %s\n", strerror (errno)); + perror_msg_and_die( "\nCannot read /etc/fstab"); while ((m = getmntent(f)) != NULL) { - // If the filesystem isn't noauto, - // and isn't swap or nfs, then mount it - if ((!strstr(m->mnt_opts, "noauto")) && - (!strstr(m->mnt_type, "swap")) && - (!strstr(m->mnt_type, "nfs"))) { + if (all == FALSE && optind + 1 == argc && ( + (strcmp(device, m->mnt_fsname) != 0) && + (strcmp(device, m->mnt_dir) != 0) ) ) { + continue; + } + + if (all == TRUE && ( // 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 or nfs, then mount it + (strstr(m->mnt_type, "nfs")) ) ) { + continue; + } + + if (all == TRUE || flags == 0) { // Allow single mount to override fstab flags flags = 0; *string_flags = '\0'; parse_mount_options(m->mnt_opts, &flags, string_flags); - /* If the directory is /, try to remount - * with the options specified in fstab */ - if (m->mnt_dir[0] == '/' && m->mnt_dir[1] == '\0') { - flags |= MS_REMOUNT; - } - if (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, - flags, string_flags, useMtab, fakeIt, - extra_opts, FALSE)) - { - /* Try again, but this time try a remount */ - mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, - flags|MS_REMOUNT, string_flags, useMtab, fakeIt, - extra_opts, TRUE); - } } - } - endmntent(f); - } else { - if (device && directory) { + + strcpy(device, m->mnt_fsname); + strcpy(directory, m->mnt_dir); + filesystemType = strdup(m->mnt_type); +singlemount: + string_flags = strdup(string_flags); + rc = EXIT_SUCCESS; #ifdef BB_NFSMOUNT + if (strchr(device, ':') != NULL) + filesystemType = "nfs"; if (strcmp(filesystemType, "nfs") == 0) { - if (nfsmount - (device, directory, &flags, &extra_opts, &string_flags, - 1) != 0) - exit(FALSE); + if (nfsmount (device, directory, &flags, &extra_opts, + &string_flags, 1)) { + perror_msg("nfsmount failed"); + rc = EXIT_FAILURE; + } } #endif - exit(mount_one(device, directory, filesystemType, - flags, string_flags, useMtab, fakeIt, - extra_opts, TRUE)); - } else { - goto goodbye; + if (!mount_one(device, directory, filesystemType, flags, + string_flags, useMtab, fakeIt, extra_opts, TRUE)) + rc = EXIT_FAILURE; + + if (all == FALSE) + break; } + if (fstabmount == TRUE) + endmntent(f); + + if (all == FALSE && fstabmount == TRUE && m == NULL) + fprintf(stderr, "Can't find %s in /etc/fstab\n", device); + + return rc; } - exit(TRUE); - - goodbye: - usage(mount_usage); + + goto singlemount; }