/* * mount(8) -- mount a filesystem * * Copyright (C) 2011 Red Hat, Inc. All rights reserved. * Written by Karel Zak * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "nls.h" #include "c.h" /*** TODO: DOCS: * * -p, --pass-fd is unsupported * --guess-fstype is unsupported * -c = --no-canonicalize */ /* exit status */ #define EX_SUCCESS 0 #define EX_USAGE 1 /* incorrect invocation or permission */ #define EX_SYSERR 2 /* out of memory, cannot fork, ... */ #define EX_SOFTWARE 4 /* internal mount bug or wrong version */ #define EX_USER 8 /* user interrupt */ #define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */ #define EX_FAIL 32 /* mount failure */ #define EX_SOMEOK 64 /* some mount succeeded */ static void __attribute__((__noreturn__)) exit_non_root(const char *option) { const uid_t ruid = getuid(); const uid_t euid = geteuid(); if (ruid == 0 && euid != 0) { /* user is root, but setuid to non-root */ if (option) errx(EX_USAGE, _("only root can use \"--%s\" option " "(effective UID is %u)"), option, euid); errx(EX_USAGE, _("only root can do that " "(effective UID is %u)"), euid); } if (option) errx(EX_USAGE, _("only root can use \"--%s\" option"), option); errx(EX_USAGE, _("only root can do that")); } static void __attribute__((__noreturn__)) print_version(void) { const char *ver = NULL; mnt_get_library_version(&ver); printf("%s from %s (libmount %s)\n", program_invocation_short_name, PACKAGE_STRING, ver); exit(EX_SUCCESS); } static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)), const char *filename, int line) { if (filename) warnx(_("%s: parse error: ignore entry at line %d."), filename, line); return 0; } static const char *opt_to_longopt(int c, const struct option *opts) { const struct option *o; for (o = opts; o->name; o++) if (o->val == c) return o->name; return NULL; } static void print_all(struct libmnt_context *cxt, char *pattern, int show_label) { struct libmnt_table *tb; struct libmnt_iter *itr = NULL; struct libmnt_fs *fs; struct libmnt_cache *cache = NULL; if (mnt_context_get_mtab(cxt, &tb)) err(EX_SYSERR, _("failed to read mtab")); itr = mnt_new_iter(MNT_ITER_FORWARD); if (!itr) err(EX_SYSERR, _("failed to initialize libmount iterator")); if (show_label) cache = mnt_new_cache(); while (mnt_table_next_fs(tb, itr, &fs) == 0) { const char *type = mnt_fs_get_fstype(fs); const char *src = mnt_fs_get_source(fs); const char *optstr = mnt_fs_get_options(fs); char *xsrc; if (type && pattern && !mnt_match_fstype(type, pattern)) continue; xsrc = mnt_pretty_path(src, cache); printf ("%s on %s", xsrc, mnt_fs_get_target(fs)); if (type) printf (" type %s", type); if (optstr) printf (" (%s)", optstr); if (show_label && src) { char *lb = mnt_cache_find_tag_value(cache, src, "LABEL"); if (lb) printf (" [%s]", lb); } fputc('\n', stdout); free(xsrc); } mnt_free_cache(cache); mnt_free_iter(itr); } /* * mount -a [-F] * ... -F is not supported yet (TODO) */ static int mount_all(struct libmnt_context *cxt, int forkme __attribute__((unused))) { struct libmnt_iter *itr; struct libmnt_fs *fs; int mntrc, ignored, rc = EX_SUCCESS; itr = mnt_new_iter(MNT_ITER_FORWARD); if (!itr) { warn(_("failed to initialize libmount iterator")); return EX_SYSERR; } while (mnt_context_next_mount(cxt, itr, &fs, &mntrc, &ignored) == 0) { const char *tgt = mnt_fs_get_target(fs); if (ignored) { if (mnt_context_is_verbose(cxt)) printf(ignored == 1 ? _("%-20s: ignored\n") : _("%-20s: already mounted\n"), tgt); } else if (!mnt_context_get_status(cxt)) { if (mntrc > 0) { errno = mntrc; printf(_("%-20s: failed: %s\n"), tgt, strerror(mntrc)); rc |= EX_FAIL; } else { printf(_("%-20s: failed\n"), tgt); rc |= EX_SYSERR; } } else { if (mnt_context_is_verbose(cxt)) printf("%-20s: successfully mounted\n", tgt); rc |= EX_SOMEOK; } } return rc; } static void __attribute__((__noreturn__)) usage(FILE *out) { fprintf(out, _("Usage:\n" " %1$s [-lhV]\n" " %1$s -a [options]\n" " %1$s [options] | \n" " %1$s [options] \n" " %1$s []\n"), program_invocation_short_name); fprintf(out, _( "\nOptions:\n" " -a, --all mount all filesystems mentioned in fstab\n" " -c, --no-canonicalize don't canonicalize paths\n" " -f, --fake dry run; skip the mount(2) syscall\n" " -F, --fork fork off for each device (use with -a)\n")); fprintf(out, _( " -h, --help display this help text and exit\n" " -i, --internal-only don't call the mount. helpers\n" " -l, --show-labels lists all mounts with LABELs\n" " -n, --no-mtab don't write to /etc/mtab\n")); fprintf(out, _( " -o, --options comma-separated list of mount options\n" " -O, --test-opts limit the set of filesystems (use with -a)\n" " -r, --read-only mount the filesystem read-only (same as -o ro)\n" " -t, --types limit the set of filesystem types\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")); fprintf(out, _( "\nSource:\n" " -L, --label