From aedeaa40d1cf5eb687a575b322a09a9a48ced623 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 17 Jul 2012 22:02:35 +0200 Subject: mount: (new) add --source and --target In some cases (for example if only one mount argument is given) may be mount request ambivalent: # mount /foo and fstab: /dev/sda5 /foo rw 0 0 /foo /bar bind 0 0 the new options allows to be more explicit # mount --target /foo (mounts /dev/sda5) # mount --source /foo (binds /foo to /bar) It's possible to use the options together # mount --source /dev/sda2 --target /home Signed-off-by: Karel Zak --- sys-utils/mount.c | 98 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 25 deletions(-) (limited to 'sys-utils/mount.c') diff --git a/sys-utils/mount.c b/sys-utils/mount.c index 9116e8081..461569f2b 100644 --- a/sys-utils/mount.c +++ b/sys-utils/mount.c @@ -355,8 +355,19 @@ try_readonly: warnx(_("%s is already mounted"), src); return MOUNT_EX_USAGE; case -MNT_ERR_NOFSTAB: - warnx(_("can't find %s in %s"), src ? src : tgt, + if (mnt_context_is_swapmatch(cxt)) { + warnx(_("can't find %s in %s"), + src ? src : tgt, mnt_get_fstab_path()); + return MOUNT_EX_USAGE; + } + /* source/target explicitly defined */ + if (tgt) + warnx(_("can't find mountpoint %s in %s"), + tgt, mnt_get_fstab_path()); + else + warnx(_("can't find mount source %s in %s"), + src, mnt_get_fstab_path()); return MOUNT_EX_USAGE; case -MNT_ERR_NOFSTYPE: if (restricted) @@ -595,7 +606,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out) fprintf(out, _( " %1$s [-lhV]\n" " %1$s -a [options]\n" - " %1$s [options] | \n" + " %1$s [options] [--source] | [--target] \n" " %1$s [options] \n" " %1$s []\n"), program_invocation_short_name); @@ -619,6 +630,9 @@ static void __attribute__((__noreturn__)) usage(FILE *out) " -r, --read-only mount the filesystem read-only (same as -o ro)\n" " -t, --types limit the set of filesystem types\n")); fprintf(out, _( + " --source explicitly specifies source (path, label, uuid)\n" + " --target explicitly specifies mountpoint\n")); + fprintf(out, _( " -v, --verbose say what is being done\n" " -V, --version display version information and exit\n" " -w, --read-write mount the filesystem read-write (default)\n")); @@ -667,7 +681,7 @@ int main(int argc, char **argv) int c, rc = MOUNT_EX_SUCCESS, all = 0, show_labels = 0; struct libmnt_context *cxt; struct libmnt_table *fstab = NULL; - char *source = NULL, *srcbuf = NULL; + char *srcbuf = NULL; char *types = NULL; unsigned long oper = 0; @@ -679,7 +693,9 @@ int main(int argc, char **argv) MOUNT_OPT_RSHARED, MOUNT_OPT_RSLAVE, MOUNT_OPT_RPRIVATE, - MOUNT_OPT_RUNBINDABLE + MOUNT_OPT_RUNBINDABLE, + MOUNT_OPT_TARGET, + MOUNT_OPT_SOURCE }; enum { @@ -692,9 +708,12 @@ int main(int argc, char **argv) EXCL_MAKE_RSHARED, EXCL_MAKE_RSLAVE, EXCL_MAKE_RPRIVATE, - EXCL_MAKE_RUNBINDABLE + EXCL_MAKE_RUNBINDABLE, + EXCL_SOURCE, + EXCL_UUID, + EXCL_LABEL }; - int excl_any = EXCL_NONE; + int excl_any = EXCL_NONE, excl_src = EXCL_NONE; static const struct option longopts[] = { { "all", 0, 0, 'a' }, @@ -729,6 +748,8 @@ int main(int argc, char **argv) { "no-canonicalize", 0, 0, 'c' }, { "internal-only", 0, 0, 'i' }, { "show-labels", 0, 0, 'l' }, + { "target", 1, 0, MOUNT_OPT_TARGET }, + { "source", 1, 0, MOUNT_OPT_SOURCE }, { NULL, 0, 0, 0 } }; @@ -749,7 +770,10 @@ int main(int argc, char **argv) longopts, NULL)) != -1) { /* only few options are allowed for non-root users */ - if (mnt_context_is_restricted(cxt) && !strchr("hlLUVvpris", c)) + if (mnt_context_is_restricted(cxt) && + !strchr("hlLUVvpris", c) && + c != MOUNT_OPT_TARGET && + c != MOUNT_OPT_SOURCE) exit_non_root(option_to_longopt(c, longopts)); switch(c) { @@ -803,13 +827,18 @@ int main(int argc, char **argv) _("invalid passphrase file descriptor")); break; case 'L': + exclusive_option(&excl_src, EXCL_LABEL, _("-L, -U and --source")); + xasprintf(&srcbuf, "LABEL=\"%s\"", optarg); + mnt_context_disable_swapmatch(cxt, 1); + mnt_context_set_source(cxt, srcbuf); + free(srcbuf); + break; case 'U': - if (source) - errx(MOUNT_EX_USAGE, _("only one may be specified")); - if (xasprintf(&srcbuf, "%s=\"%s\"", - c == 'L' ? "LABEL" : "UUID", optarg) <= 0) - err(MOUNT_EX_SYSERR, _("failed to allocate source buffer")); - source = srcbuf; + exclusive_option(&excl_src, EXCL_UUID, _("-L, -U and --source")); + xasprintf(&srcbuf, "UUID=\"%s\"", optarg); + mnt_context_disable_swapmatch(cxt, 1); + mnt_context_set_source(cxt, srcbuf); + free(srcbuf); break; case 'l': show_labels = 1; @@ -865,6 +894,15 @@ int main(int argc, char **argv) exclusive_option(&excl_any, EXCL_MAKE_RUNBINDABLE, EXCL_ERROR); oper |= (MS_UNBINDABLE | MS_REC); break; + case MOUNT_OPT_TARGET: + mnt_context_disable_swapmatch(cxt, 1); + mnt_context_set_target(cxt, optarg); + break; + case MOUNT_OPT_SOURCE: + exclusive_option(&excl_src, EXCL_SOURCE, _("-L, -U and --source")); + mnt_context_disable_swapmatch(cxt, 1); + mnt_context_set_source(cxt, optarg); + break; default: usage(stderr); break; @@ -874,14 +912,17 @@ int main(int argc, char **argv) argc -= optind; argv += optind; - if (!source && !argc && !all) { + if (!mnt_context_get_source(cxt) && + !mnt_context_get_target(cxt) && + !argc && + !all) { if (oper) usage(stderr); print_all(cxt, types, show_labels); goto done; } - if (oper && (types || all || source)) + if (oper && (types || all || mnt_context_get_source(cxt))) usage(stderr); if (types && (all || strchr(types, ',') || @@ -899,25 +940,31 @@ int main(int argc, char **argv) rc = mount_all(cxt); goto done; - } else if (argc == 0 && source) { + } else if (argc == 0 && (mnt_context_get_source(cxt) || + mnt_context_get_target(cxt))) { /* - * B) mount -L|-U + * B) mount -L|-U|--source|--target */ - mnt_context_set_source(cxt, source); + if (mnt_context_is_restricted(cxt) && + mnt_context_get_source(cxt) && + mnt_context_get_target(cxt)) + exit_non_root(NULL); } else if (argc == 1) { /* - * C) mount [-L|-U] + * C) mount [-L|-U|--source] * mount + * + * non-root may specify source *or* target, but not both */ - if (source) { - if (mnt_context_is_restricted(cxt)) - exit_non_root(NULL); - mnt_context_set_source(cxt, source); - } + if (mnt_context_is_restricted(cxt) && + mnt_context_get_source(cxt)) + exit_non_root(NULL); + mnt_context_set_target(cxt, argv[0]); - } else if (argc == 2 && !source) { + } else if (argc == 2 && !mnt_context_get_source(cxt) + && !mnt_context_get_target(cxt)) { /* * D) mount */ @@ -925,6 +972,7 @@ int main(int argc, char **argv) exit_non_root(NULL); mnt_context_set_source(cxt, argv[0]); mnt_context_set_target(cxt, argv[1]); + } else usage(stderr); -- cgit v1.2.3-55-g7522