#if defined(__dietlibc__)
/* 16.12.2006, Sampo Kellomaki (sampo@iki.fi)
* dietlibc-0.30 does not have implementation of getmntent_r() */
-static struct mntent *getmntent_r(FILE* stream, struct mntent* result, char* buffer, int bufsize)
+static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
+ char* buffer UNUSED_PARAM, int bufsize UNUSED_PARAM)
{
struct mntent* ment = getmntent(stream);
- memcpy(result, ment, sizeof(struct mntent));
- return result;
+ return memcpy(result, ment, sizeof(*ment));
}
#endif
/* "noatime" */ MS_NOATIME,
/* "diratime" */ ~MS_NODIRATIME,
/* "nodiratime" */ MS_NODIRATIME,
+ /* "mand" */ MS_MANDLOCK,
+ /* "nomand" */ ~MS_MANDLOCK,
/* "loud" */ ~MS_SILENT,
// action flags
"noatime" "\0"
"diratime" "\0"
"nodiratime" "\0"
+ "mand" "\0"
+ "nomand" "\0"
"loud" "\0"
// action flags
if (comma) *comma = '\0';
+/* FIXME: use hasmntopt() */
// Find this option in mount_options
for (i = 0; i < ARRAY_SIZE(mount_options); i++) {
if (!strcasecmp(option_str, options)) {
if (unrecognized && i == ARRAY_SIZE(mount_options)) {
// Add it to strflags, to pass on to kernel
i = *unrecognized ? strlen(*unrecognized) : 0;
- *unrecognized = xrealloc(*unrecognized, i+strlen(options)+2);
+ *unrecognized = xrealloc(*unrecognized, i + strlen(options) + 2);
// Comma separated if it's not the first one
if (i) (*unrecognized)[i++] = ',';
FILE *f;
for (i = 0; i < 2; i++) {
- f = fopen(filesystems[i], "r");
+ f = fopen_for_read(filesystems[i]);
if (!f) continue;
while ((buf = xmalloc_fgetline(f)) != NULL) {
vfsflags, filteropts);
// If mount failed, try
- // helper program <mnt_type>
+ // helper program mount.<mnt_type>
if (ENABLE_FEATURE_MOUNT_HELPERS && rc) {
char *args[6];
int errno_save = errno;
NFS_MOUNT_TCP = 0x0040, /* 2 */
NFS_MOUNT_VER3 = 0x0080, /* 3 */
NFS_MOUNT_KERBEROS = 0x0100, /* 3 */
- NFS_MOUNT_NONLM = 0x0200 /* 3 */
+ NFS_MOUNT_NONLM = 0x0200, /* 3 */
+ NFS_MOUNT_NORDIRPLUS = 0x4000
};
#if BB_MMU
static int daemonize(void)
{
- int fd;
int pid = fork();
if (pid < 0) /* error */
return -errno;
if (pid > 0) /* parent */
return 0;
/* child */
- fd = xopen(bb_dev_null, O_RDWR);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- while (fd > 2) close(fd--);
+ close(0);
+ xopen(bb_dev_null, O_RDWR);
+ xdup2(0, 1);
+ xdup2(0, 2);
setsid();
openlog(applet_name, LOG_PID, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
#endif
// TODO
-static inline int we_saw_this_host_before(const char *hostname ATTRIBUTE_UNUSED)
+static inline int we_saw_this_host_before(const char *hostname UNUSED_PARAM)
{
return 0;
}
int mountport;
int proto;
#if BB_MMU
- int bg = 0;
+ smallint bg = 0;
#else
enum { bg = 0 };
#endif
- int soft;
- int intr;
- int posix;
- int nocto;
- int noac;
- int nolock;
int retry;
- int tcp;
int mountprog;
int mountvers;
int nfsprog;
int nfsvers;
int retval;
+ /* these all are one-bit really. 4.3.1 likes this combination: */
+ smallint tcp;
+ smallint soft;
+ int intr;
+ int posix;
+ int nocto;
+ int noac;
+ int nordirplus;
+ int nolock;
find_kernel_nfs_mount_version();
* let the kernel decide.
* timeo is filled in after we know whether it'll be TCP or UDP. */
memset(&data, 0, sizeof(data));
- data.retrans = 3;
- data.acregmin = 3;
- data.acregmax = 60;
- data.acdirmin = 30;
- data.acdirmax = 60;
- data.namlen = NAME_MAX;
+ data.retrans = 3;
+ data.acregmin = 3;
+ data.acregmax = 60;
+ data.acdirmin = 30;
+ data.acdirmax = 60;
+ data.namlen = NAME_MAX;
soft = 0;
intr = 0;
nocto = 0;
nolock = 0;
noac = 0;
+ nordirplus = 0;
retry = 10000; /* 10000 minutes ~ 1 week */
tcp = 0;
if (filteropts) for (opt = strtok(filteropts, ","); opt; opt = strtok(NULL, ",")) {
char *opteq = strchr(opt, '=');
if (opteq) {
+ int val, idx;
static const char options[] ALIGN1 =
/* 0 */ "rsize\0"
/* 1 */ "wsize\0"
/* 18 */ "proto\0"
/* 19 */ "namlen\0"
/* 20 */ "addr\0";
- int val = xatoi_u(opteq + 1);
- *opteq = '\0';
- switch (index_in_strings(options, opt)) {
+
+ *opteq++ = '\0';
+ idx = index_in_strings(options, opt);
+ switch (idx) {
+ case 12: // "mounthost"
+ mounthost = xstrndup(opteq,
+ strcspn(opteq, " \t\n\r,"));
+ continue;
+ case 18: // "proto"
+ if (!strncmp(opteq, "tcp", 3))
+ tcp = 1;
+ else if (!strncmp(opteq, "udp", 3))
+ tcp = 0;
+ else
+ bb_error_msg("warning: unrecognized proto= option");
+ continue;
+ case 20: // "addr" - ignore
+ continue;
+ }
+
+ val = xatoi_u(opteq);
+ switch (idx) {
case 0: // "rsize"
data.rsize = val;
- break;
+ continue;
case 1: // "wsize"
data.wsize = val;
- break;
+ continue;
case 2: // "timeo"
data.timeo = val;
- break;
+ continue;
case 3: // "retrans"
data.retrans = val;
- break;
+ continue;
case 4: // "acregmin"
data.acregmin = val;
- break;
+ continue;
case 5: // "acregmax"
data.acregmax = val;
- break;
+ continue;
case 6: // "acdirmin"
data.acdirmin = val;
- break;
+ continue;
case 7: // "acdirmax"
data.acdirmax = val;
- break;
+ continue;
case 8: // "actimeo"
data.acregmin = val;
data.acregmax = val;
data.acdirmin = val;
data.acdirmax = val;
- break;
+ continue;
case 9: // "retry"
retry = val;
- break;
+ continue;
case 10: // "port"
port = val;
- break;
+ continue;
case 11: // "mountport"
mountport = val;
- break;
- case 12: // "mounthost"
- mounthost = xstrndup(opteq+1,
- strcspn(opteq+1," \t\n\r,"));
- break;
+ continue;
case 13: // "mountprog"
mountprog = val;
- break;
+ continue;
case 14: // "mountvers"
mountvers = val;
- break;
+ continue;
case 15: // "nfsprog"
nfsprog = val;
- break;
+ continue;
case 16: // "nfsvers"
case 17: // "vers"
nfsvers = val;
- break;
- case 18: // "proto"
- if (!strncmp(opteq+1, "tcp", 3))
- tcp = 1;
- else if (!strncmp(opteq+1, "udp", 3))
- tcp = 0;
- else
- bb_error_msg("warning: unrecognized proto= option");
- break;
+ continue;
case 19: // "namlen"
- if (nfs_mount_version >= 2)
+ //if (nfs_mount_version >= 2)
data.namlen = val;
- else
- bb_error_msg("warning: option namlen is not supported\n");
- break;
- case 20: // "addr" - ignore
- break;
+ //else
+ // bb_error_msg("warning: option namlen is not supported\n");
+ continue;
default:
bb_error_msg("unknown nfs mount parameter: %s=%d", opt, val);
goto fail;
}
}
- else {
+ else { /* not of the form opt=val */
static const char options[] ALIGN1 =
"bg\0"
"fg\0"
"ac\0"
"tcp\0"
"udp\0"
- "lock\0";
+ "lock\0"
+ "rdirplus\0";
int val = 1;
if (!strncmp(opt, "no", 2)) {
val = 0;
else
bb_error_msg("warning: option nolock is not supported");
break;
+ case 11: //rdirplus
+ nordirplus = !val;
+ break;
default:
bb_error_msg("unknown nfs mount option: %s%s", val ? "" : "no", opt);
goto fail;
| (intr ? NFS_MOUNT_INTR : 0)
| (posix ? NFS_MOUNT_POSIX : 0)
| (nocto ? NFS_MOUNT_NOCTO : 0)
- | (noac ? NFS_MOUNT_NOAC : 0);
+ | (noac ? NFS_MOUNT_NOAC : 0)
+ | (nordirplus ? NFS_MOUNT_NORDIRPLUS : 0);
if (nfs_mount_version >= 2)
data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
if (nfs_mount_version >= 3)
retry_timeout.tv_usec = 0;
total_timeout.tv_sec = 20;
total_timeout.tv_usec = 0;
+//FIXME: use monotonic()?
timeout = time(NULL) + 60 * retry;
prevt = 0;
t = 30;
if (!daemonized) {
daemonized = daemonize();
if (daemonized <= 0) { /* parent or error */
- // FIXME: parent doesn't close fsock - ??!
+// FIXME: parent doesn't close fsock - ??!
retval = -daemonized;
goto ret;
}
static const char must_be_root[] ALIGN1 = "you must be root";
int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int mount_main(int argc, char **argv)
+int mount_main(int argc UNUSED_PARAM, char **argv)
{
char *cmdopts = xstrdup("");
char *fstype = NULL;
- char *storage_path = NULL;
+ char *storage_path;
char *opt_o;
const char *fstabname;
FILE *fstab;
struct mntent mtpair[2], *mtcur = mtpair;
SKIP_DESKTOP(const int nonroot = 0;)
- USE_DESKTOP( int nonroot = ) sanitize_env_if_suid();
+ USE_DESKTOP(int nonroot = ) sanitize_env_if_suid();
// Parse long options, like --bind and --move. Note that -o option
// and --option are synonymous. Yes, this means --remount,rw works.
-
- for (i = j = 0; i < argc; i++) {
- if (argv[i][0] == '-' && argv[i][1] == '-') {
- append_mount_options(&cmdopts, argv[i]+2);
- } else argv[j++] = argv[i];
+ for (i = j = 1; argv[i]; i++) {
+ if (argv[i][0] == '-' && argv[i][1] == '-')
+ append_mount_options(&cmdopts, argv[i] + 2);
+ else
+ argv[j++] = argv[i];
}
argv[j] = NULL;
- argc = j;
// Parse remaining options
-
-#if ENABLE_FEATURE_MOUNT_VERBOSE
- opt_complementary = "vv"; // -v is a counter
-#endif
+ // Max 2 params; -v is a counter
+ opt_complementary = "?2" USE_FEATURE_MOUNT_VERBOSE(":vv");
opt = getopt32(argv, OPTION_STR, &opt_o, &fstype
USE_FEATURE_MOUNT_VERBOSE(, &verbose));
if (opt & OPT_o) append_mount_options(&cmdopts, opt_o); // -o
if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r
if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w
argv += optind;
- argc -= optind;
-
- // Three or more non-option arguments? Die with a usage message.
-
- if (argc > 2) bb_show_usage();
// If we have no arguments, show currently mounted filesystems
-
- if (!argc) {
+ if (!argv[0]) {
if (!(opt & OPT_a)) {
FILE *mountTable = setmntent(bb_path_mtab_file, "r");
- if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file);
+ if (!mountTable)
+ bb_error_msg_and_die("no %s", bb_path_mtab_file);
while (getmntent_r(mountTable, &mtpair[0], getmntent_buf,
GETMNTENT_BUFSIZE))
mtpair->mnt_dir, mtpair->mnt_type,
mtpair->mnt_opts);
}
- if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ endmntent(mountTable);
return EXIT_SUCCESS;
}
- } else storage_path = bb_simplify_path(argv[0]);
-
- // When we have two arguments, the second is the directory and we can
- // skip looking at fstab entirely. We can always abspath() the directory
- // argument when we get it.
-
- if (argc == 2) {
- if (nonroot)
- bb_error_msg_and_die(must_be_root);
- mtpair->mnt_fsname = argv[0];
- mtpair->mnt_dir = argv[1];
- mtpair->mnt_type = fstype;
- mtpair->mnt_opts = cmdopts;
- if (ENABLE_FEATURE_MOUNT_LABEL) {
- resolve_mount_spec(&mtpair->mnt_fsname);
+ storage_path = NULL;
+ } else {
+ // When we have two arguments, the second is the directory and we can
+ // skip looking at fstab entirely. We can always abspath() the directory
+ // argument when we get it.
+ if (argv[1]) {
+ if (nonroot)
+ bb_error_msg_and_die(must_be_root);
+ mtpair->mnt_fsname = argv[0];
+ mtpair->mnt_dir = argv[1];
+ mtpair->mnt_type = fstype;
+ mtpair->mnt_opts = cmdopts;
+ if (ENABLE_FEATURE_MOUNT_LABEL) {
+ resolve_mount_spec(&mtpair->mnt_fsname);
+ }
+ rc = singlemount(mtpair, 0);
+ return rc;
}
- rc = singlemount(mtpair, 0);
- goto clean_up;
+ storage_path = bb_simplify_path(argv[0]); // malloced
}
+ // Past this point, we are handling either "mount -a [opts]"
+ // or "mount [opts] single_param"
+
i = parse_mount_options(cmdopts, 0); // FIXME: should be "long", not "int"
if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags
bb_error_msg_and_die(must_be_root);
// If we have a shared subtree flag, don't worry about fstab or mtab.
-
if (ENABLE_FEATURE_MOUNT_FLAGS
&& (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
) {
- rc = verbose_mount("", argv[0], "", i, "");
- if (rc) bb_simple_perror_msg_and_die(argv[0]);
- goto clean_up;
+ rc = verbose_mount(/*source:*/ "", /*target:*/ argv[0],
+ /*type:*/ "", /*flags:*/ i, /*data:*/ "");
+ if (rc)
+ bb_simple_perror_msg_and_die(argv[0]);
+ return rc;
}
// Open either fstab or mtab
-
fstabname = "/etc/fstab";
if (i & MS_REMOUNT) {
+ // WARNING. I am not sure this matches util-linux's
+ // behavior. It's possible util-linux does not
+ // take -o opts from mtab (takes only mount source).
fstabname = bb_path_mtab_file;
}
fstab = setmntent(fstabname, "r");
if (!fstab)
bb_perror_msg_and_die("cannot read %s", fstabname);
- // Loop through entries until we find what we're looking for.
-
+ // Loop through entries until we find what we're looking for
memset(mtpair, 0, sizeof(mtpair));
for (;;) {
- struct mntent *mtnext = (mtcur==mtpair ? mtpair+1 : mtpair);
+ struct mntent *mtother = (mtcur==mtpair ? mtpair+1 : mtpair);
// Get next fstab entry
-
if (!getmntent_r(fstab, mtcur, getmntent_buf
+ (mtcur==mtpair ? GETMNTENT_BUFSIZE/2 : 0),
- GETMNTENT_BUFSIZE/2))
- {
- // Were we looking for something specific?
-
- if (argc) {
-
- // If we didn't find anything, complain.
-
- if (!mtnext->mnt_fsname)
- bb_error_msg_and_die("can't find %s in %s",
- argv[0], fstabname);
-
- mtcur = mtnext;
- if (nonroot) {
- // fstab must have "users" or "user"
- if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS))
- bb_error_msg_and_die(must_be_root);
- }
-
- // Mount the last thing we found.
-
- mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
- append_mount_options(&(mtcur->mnt_opts), cmdopts);
- if (ENABLE_FEATURE_MOUNT_LABEL) {
- resolve_mount_spec(&mtpair->mnt_fsname);
- }
- rc = singlemount(mtcur, 0);
- free(mtcur->mnt_opts);
- }
- goto clean_up;
+ GETMNTENT_BUFSIZE/2)
+ ) { // End of fstab/mtab is reached
+ mtcur = mtother; // the thing we found last time
+ break;
}
- /* If we're trying to mount 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 */
-
- if (argc) {
+ // If we're trying to mount something specific and this isn't it,
+ // skip it. Note we must match the exact text in fstab (ala
+ // "proc") or a full path from root
+ if (argv[0]) {
// Is this what we're looking for?
-
if (strcmp(argv[0], mtcur->mnt_fsname) &&
strcmp(storage_path, mtcur->mnt_fsname) &&
strcmp(argv[0], mtcur->mnt_dir) &&
strcmp(storage_path, mtcur->mnt_dir)) continue;
- // Remember this entry. Something later may have overmounted
- // it, and we want the _last_ match.
-
- mtcur = mtnext;
-
- // If we're mounting all.
+ // Remember this entry. Something later may have
+ // overmounted it, and we want the _last_ match.
+ mtcur = mtother;
+ // If we're mounting all
} else {
// Do we need to match a filesystem type?
if (fstype && match_fstype(mtcur, fstype))
continue;
// Skip noauto and swap anyway.
-
if (parse_mount_options(mtcur->mnt_opts, 0) & (MOUNT_NOAUTO | MOUNT_SWAP))
continue;
// No, mount -a won't mount anything,
- // even user mounts, for mere humans.
-
+ // even user mounts, for mere humans
if (nonroot)
bb_error_msg_and_die(must_be_root);
- // Mount this thing.
+ // Mount this thing
if (ENABLE_FEATURE_MOUNT_LABEL)
resolve_mount_spec(&mtpair->mnt_fsname);
// NFS mounts want this to be xrealloc-able
mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
if (singlemount(mtcur, 1)) {
- /* Count number of failed mounts */
+ // Count number of failed mounts
rc++;
}
free(mtcur->mnt_opts);
}
}
- if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab);
- clean_up:
+ // End of fstab/mtab is reached.
+ // Were we looking for something specific?
+ if (argv[0]) {
+ // If we didn't find anything, complain
+ if (!mtcur->mnt_fsname)
+ bb_error_msg_and_die("can't find %s in %s",
+ argv[0], fstabname);
+ if (nonroot) {
+ // fstab must have "users" or "user"
+ if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS))
+ bb_error_msg_and_die(must_be_root);
+ }
+
+ // Mount the last thing we found
+ mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
+ append_mount_options(&(mtcur->mnt_opts), cmdopts);
+ if (ENABLE_FEATURE_MOUNT_LABEL) {
+ resolve_mount_spec(&mtpair->mnt_fsname);
+ }
+ rc = singlemount(mtcur, 0);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(mtcur->mnt_opts);
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ endmntent(fstab);
if (ENABLE_FEATURE_CLEAN_UP) {
free(storage_path);
free(cmdopts);
}
-
return rc;
}