*
* 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 "internal.h"
+#include "busybox.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <linux/devmtab.h> /* For Erik's nifty devmtab device driver */
#endif
-
-#define MS_MGC_VAL 0xc0ed0000 /* Magic number indicatng "new" flags */
-#define MS_RDONLY 1 /* Mount read-only */
-#define MS_NOSUID 2 /* Ignore suid and sgid bits */
-#define MS_NODEV 4 /* Disallow access to device special files */
-#define MS_NOEXEC 8 /* Disallow program execution */
-#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
-#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
-#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
-#define S_QUOTA 128 /* Quota initialized for file/directory/symlink */
-#define S_APPEND 256 /* Append-only file */
-#define S_IMMUTABLE 512 /* Immutable file */
-#define MS_NOATIME 1024 /* Do not update access times. */
-#define MS_NODIRATIME 2048 /* Do not update directory access times */
-
+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 */
+};
#if defined BB_FEATURE_MOUNT_LOOP
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) {
specialfile = find_unused_loop_device();
if (specialfile == NULL) {
- errorMsg("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)) {
- errorMsg("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 */
- errorMsg("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);
+ 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 (useMtab == TRUE) {
+ erase_mtab(specialfile); // Clean any stale entries
write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
}
#endif
#endif
if (errno == EPERM) {
- fatalError("permission denied. Are you root?\n");
+ error_msg_and_die("permission denied. Are you root?");
}
return (FALSE);
{
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);
+ FILE *f = xfopen("/proc/filesystems", "r");
while (fgets(buf, sizeof(buf), f) != NULL) {
filesystemType = buf;
}
fclose(f);
} else
-#endif
#if defined BB_FEATURE_USE_DEVPS_PATCH
if (strcmp(filesystemType, "auto") == 0) {
int fd, i, numfilesystems;
/* open device */
fd = open(device, O_RDONLY);
if (fd < 0)
- fatalError("open failed for `%s': %s\n", device, strerror (errno));
+ perror_msg_and_die("open failed for `%s'", device);
/* 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));
+ perror_msg_and_die("\nDEVMTAB_COUNT_FILESYSTEMS");
+ fslist = (struct k_fstype *) xcalloc ( 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));
+ perror_msg_and_die("\nDEVMTAB_GET_FILESYSTEMS");
/* Walk the list trying to mount filesystems
* that do not claim to be nodev filesystems */
if (status == FALSE) {
if (whineOnErrors == TRUE) {
- errorMsg("Mounting %s on %s failed: %s\n",
- blockDevice, directory, strerror(errno));
+ perror_msg("Mounting %s on %s failed", blockDevice, directory);
}
return (FALSE);
}
int fakeIt = FALSE;
int useMtab = TRUE;
int i;
+ int rc = EXIT_FAILURE;
+ int fstabmount = FALSE;
#if defined BB_FEATURE_USE_DEVPS_PATCH
if (argc == 1) {
/* open device */
fd = open(device, O_RDONLY);
if (fd < 0)
- fatalError("open failed for `%s': %s\n", device, strerror (errno));
+ 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)
- fatalError( "\nDEVMTAB_COUNT_MOUNTS: %s\n", strerror (errno));
- mntentlist = (struct k_mntent *) calloc ( numfilesystems, sizeof(struct k_mntent));
+ 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)
- fatalError( "\nDEVMTAB_GET_MOUNTS: %s\n", strerror (errno));
+ perror_msg_and_die( "\nDEVMTAB_GET_MOUNTS");
for( i = 0 ; i < numfilesystems ; i++) {
- fprintf( stdout, "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname,
+ 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);
free( mntentlist);
close(fd);
#endif
- exit(TRUE);
+ return EXIT_SUCCESS;
}
#else
if (argc == 1) {
}
endmntent(mountTable);
} else {
- perror(mtab_file);
+ perror_msg_and_die("%s", mtab_file);
}
- exit(TRUE);
+ return EXIT_SUCCESS;
}
#endif
argv++;
}
- if (all == TRUE) {
+ if (all == TRUE || directory == NULL) {
struct mntent *m;
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 && directory == NULL && (
+ (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 (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
- flags, string_flags, useMtab, fakeIt,
- extra_opts, FALSE)==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) {
+
+ device = strdup(m->mnt_fsname);
+ directory = strdup(m->mnt_dir);
+ filesystemType = strdup(m->mnt_type);
+singlemount:
+ rc = EXIT_SUCCESS;
#ifdef BB_NFSMOUNT
if (strchr(device, ':') != NULL)
filesystemType = "nfs";
if (strcmp(filesystemType, "nfs") == 0) {
- int ret;
- ret = nfsmount (device, directory, &flags,
- &extra_opts, &string_flags, 1);
- if (ret != 0)
- fatalError("nfsmount failed: %s\n", strerror(errno));
+ rc = nfsmount (device, directory, &flags,
+ &extra_opts, &string_flags, 1);
+ if ( rc != 0) {
+ perror_msg_and_die("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 && directory == NULL)
+ fprintf(stderr, "Can't find %s in /etc/fstab\n", device);
+
+ exit(rc);
}
- exit(TRUE);
-
- goodbye:
+
+ goto singlemount;
+
+goodbye:
usage(mount_usage);
}