]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add support for mount -a
authorKarel Zak <kzak@redhat.com>
Thu, 23 Jun 2011 13:07:55 +0000 (15:07 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 23 Jun 2011 13:07:55 +0000 (15:07 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/samples/mount.c
libmount/src/context.c
libmount/src/context_mount.c
libmount/src/libmount.h.in
libmount/src/libmount.sym
libmount/src/optstr.c

index 21a7edbf81cfddb8535a591bd12e402f382ff88b..3bcd5d9b5db89ab908151caf86bd93770b59ab84 100644 (file)
 #define EX_FAIL               32       /* mount failure */
 #define EX_SOMEOK      64      /* some mount succeeded */
 
-static struct libmnt_lock *lock;
-
-static void lock_atexit_cleanup(void)
-{
-       if (lock)
-               mnt_unlock_file(lock);
-}
-
 static void __attribute__((__noreturn__)) exit_non_root(const char *option)
 {
        const uid_t ruid = getuid();
@@ -87,6 +79,15 @@ static void __attribute__((__noreturn__)) print_version(void)
        exit(EX_SUCCESS);
 }
 
+static int table_parser_errcb(struct libmnt_table *tb,
+                       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;
@@ -110,13 +111,14 @@ static int print_all(struct libmnt_context *cxt, char *pattern, int show_label)
                goto done;
 
        itr = mnt_new_iter(MNT_ITER_FORWARD);
-       if (!itr)
+       if (!itr) {
+               warn(_("failed to initialize libmount iterator"));
                goto done;
-
+       }
        if (show_label)
                cache = mnt_new_cache();
 
-       while(mnt_table_next_fs(tb, itr, &fs) == 0) {
+       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);
@@ -144,10 +146,51 @@ done:
        return rc;
 }
 
-static int mount_all(struct libmnt_context *cxt)
+/*
+ * mount -a [-F]
+ * ... -F is not supported yet (TODO)
+ */
+static int mount_all(struct libmnt_context *cxt,
+                    int forkme __attribute__((unused)))
 {
-       warnx(_("mount -a is not implemented yet"));
-       return EXIT_FAILURE;
+       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)
@@ -208,7 +251,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
 
 int main(int argc, char **argv)
 {
-       int c, rc = EXIT_FAILURE, all = 0, show_labels = 0;
+       int c, rc = EXIT_FAILURE, all = 0, forkme = 0, show_labels = 0;
        struct libmnt_context *cxt;
        char *source = NULL, *srcbuf = NULL;
        char *types = NULL;
@@ -257,6 +300,8 @@ int main(int argc, char **argv)
        if (!cxt)
                err(EX_SYSERR, _("libmount context allocation failed"));
 
+       mnt_context_set_tables_errcb(cxt, table_parser_errcb);
+
        while ((c = getopt_long(argc, argv, "aBcfFhilL:Mno:O:rRsU:vVwt:",
                                        longopts, NULL)) != -1) {
 
@@ -275,7 +320,7 @@ int main(int argc, char **argv)
                        mnt_context_enable_fake(cxt, TRUE);
                        break;
                case 'F':
-                       err(EX_FAIL, "-F not implemented yet"); /* TODO */
+                       forkme = 1;
                        break;
                case 'h':
                        usage(stdout);
@@ -379,7 +424,8 @@ int main(int argc, char **argv)
        if (oper && (types || all || source))
                usage(stderr);
 
-       if (types && (strchr(types, ',') || strncmp(types, "no", 2) == 0))
+       if (types && (all || strchr(types, ',') ||
+                            strncmp(types, "no", 2) == 0))
                mnt_context_set_fstype_pattern(cxt, types);
        else if (types)
                mnt_context_set_fstype(cxt, types);
@@ -388,7 +434,7 @@ int main(int argc, char **argv)
                /*
                 * A) Mount all
                 */
-               rc = mount_all(cxt);
+               rc = mount_all(cxt, forkme);
                mnt_free_context(cxt);
                return rc;
 
@@ -424,11 +470,9 @@ int main(int argc, char **argv)
        if (oper)
                mnt_context_set_mflags(cxt, oper);
 
-       lock = mnt_context_get_lock(cxt);
-       if (lock)
-               atexit(lock_atexit_cleanup);
-
        rc = mnt_context_mount(cxt);
+       rc = rc ? EX_FAIL : EX_SUCCESS;
+
        if (rc) {
                /* TODO: call mnt_context_strerror() */
                rc = EX_FAIL;
index 681b0575ba9b0e64a2890b16881544cf0204aa4c..ff199ea2e59400a1f4daeccdeb6b628a4ce859d9 100644 (file)
@@ -66,7 +66,7 @@ struct libmnt_context *mnt_new_context(void)
        /* if we're really root and aren't running setuid */
        cxt->restricted = (uid_t) 0 == ruid && ruid == euid ? 0 : 1;
 
-       DBG(CXT, mnt_debug_h(cxt, "allocate %s",
+       DBG(CXT, mnt_debug_h(cxt, "----> allocate %s",
                                cxt->restricted ? "[RESTRICTED]" : ""));
 
        mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable);
@@ -103,7 +103,7 @@ void mnt_free_context(struct libmnt_context *cxt)
        mnt_free_lock(cxt->lock);
        mnt_free_update(cxt->update);
 
-       DBG(CXT, mnt_debug_h(cxt, "free"));
+       DBG(CXT, mnt_debug_h(cxt, "<---- free"));
        free(cxt);
 }
 
@@ -134,10 +134,8 @@ int mnt_reset_context(struct libmnt_context *cxt)
        if (!cxt)
                return -EINVAL;
 
-       DBG(CXT, mnt_debug_h(cxt,
-               "reset [status=%d %s]",
-               mnt_context_get_status(cxt),
-               mnt_context_get_status(cxt) == 0 ? "FAILED" : "SUCCESS"));
+       DBG(CXT, mnt_debug_h(cxt, "<---- reset [status=%d] ---->",
+                               mnt_context_get_status(cxt)));
 
        fl = cxt->flags;
 
@@ -165,7 +163,16 @@ int mnt_reset_context(struct libmnt_context *cxt)
        /* restore non-resetable flags */
        cxt->flags |= (fl & MNT_FL_EXTERN_FSTAB);
        cxt->flags |= (fl & MNT_FL_EXTERN_CACHE);
-
+       cxt->flags |= (fl & MNT_FL_NOMTAB);
+       cxt->flags |= (fl & MNT_FL_FAKE);
+       cxt->flags |= (fl & MNT_FL_SLOPPY);
+       cxt->flags |= (fl & MNT_FL_VERBOSE);
+       cxt->flags |= (fl & MNT_FL_NOHELPERS);
+       cxt->flags |= (fl & MNT_FL_LOOPDEL);
+       cxt->flags |= (fl & MNT_FL_LAZY);
+       cxt->flags |= (fl & MNT_FL_FORCE);
+       cxt->flags |= (fl & MNT_FL_NOCANONICALIZE);
+       cxt->flags |= (fl & MNT_FL_RDONLY_UMOUNT);
        return 0;
 }
 
@@ -1556,7 +1563,7 @@ int mnt_context_get_status(struct libmnt_context *cxt)
 /**
  * mnt_context_set_syscall_status:
  * @cxt: mount context
- * @status: mount(2) return code
+ * @status: mount(2) status
  *
  * The @status should be 0 on succcess, or negative number on error (-1 or
  * -errno).
@@ -1645,6 +1652,30 @@ int mnt_context_helper_setopt(struct libmnt_context *cxt, int c, char *arg)
        return -EINVAL;
 }
 
+/**
+ * @cxt: context
+ * @fs; filesystem
+ * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
+ *
+ * Returns: 0 on success and negative number in case of error.
+ */
+int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
+                             struct libmnt_fs *fs, int *mounted)
+{
+       struct libmnt_table *mtab;
+       int rc;
+
+       if (!cxt || !fs || !mounted)
+               return -EINVAL;
+
+       rc = mnt_context_get_mtab(cxt, &mtab);
+       if (rc)
+               return rc;
+
+       *mounted = mnt_table_is_fs_mounted(mtab, fs);
+       return 0;
+}
+
 #ifdef TEST_PROGRAM
 
 struct libmnt_lock *lock;
@@ -1796,15 +1827,62 @@ int test_flags(struct libmnt_test *ts, int argc, char *argv[])
        return rc;
 }
 
+int test_mountall(struct libmnt_test *ts, int argc, char *argv[])
+{
+       struct libmnt_context *cxt;
+       struct libmnt_iter *itr;
+       struct libmnt_fs *fs;
+       int mntrc, ignored, idx = 1;
+
+       cxt = mnt_new_context();
+       itr = mnt_new_iter(MNT_ITER_FORWARD);
+
+       if (!cxt || !itr)
+               return -ENOMEM;
+
+       if (argc > 2) {
+               if (!strcmp(argv[idx], "-O")) {
+                       mnt_context_set_options_pattern(cxt, argv[idx + 1]);
+                       idx += 2;
+               }
+               if (!strcmp(argv[idx], "-t")) {
+                       mnt_context_set_fstype_pattern(cxt, argv[idx + 1]);
+                       idx += 2;
+               }
+       }
+
+       while (mnt_context_next_mount(cxt, itr, &fs, &mntrc, &ignored) == 0) {
+
+               const char *tgt = mnt_fs_get_target(fs);
+
+               if (ignored == 1)
+                       printf("%s: ignored: not match\n", tgt);
+               else if (ignored == 2)
+                       printf("%s: ignored: already mounted\n", tgt);
+
+               else if (!mnt_context_get_status(cxt)) {
+                       if (mntrc > 0) {
+                               errno = mntrc;
+                               warn("%s: mount failed", tgt);
+                       } else
+                               warnx("%s: mount failed", tgt);
+               } else
+                       printf("%s: successfully mounted\n", tgt);
+       }
+
+       mnt_free_context(cxt);
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        struct libmnt_test tss[] = {
        { "--mount",  test_mount,  "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
        { "--umount", test_umount, "[-t <type>] [-f][-l][-r] <src>|<target>" },
+       { "--mount-all", test_mountall,  "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
        { "--flags", test_flags,   "[-o <opts>] <spec>" },
        { NULL }};
 
-
        umask(S_IWGRP|S_IWOTH); /* to be compatible with mount(8) */
 
        return mnt_run_test(tss, argc, argv);
index 58c3ec10ed7073dae7f6597d0bca3cf8650e9a0b..53bb3a735e86ba97d12b8fbf896dbd5ecdfe8bf5 100644 (file)
@@ -359,6 +359,10 @@ static int exec_helper(struct libmnt_context *cxt)
 /*
  * The default is to use fstype from cxt->fs, this could be overwritten by
  * @try_type argument.
+ *
+ * Returns: 0 on success,
+ *         >0 in case of mount(2) error (returns syscall errno),
+ *         <0 in case of other errors.
  */
 static int do_mount(struct libmnt_context *cxt, const char *try_type)
 {
@@ -608,7 +612,7 @@ int mnt_context_finalize_mount(struct libmnt_context *cxt)
  *          mount.type helper wasn't sucessfully called.
  *
  *          Check mnt_context_get_status() after error!
-*
+ *
  * Returns: 0 on success;
  *         >0 in case of mount(2) error (returns syscall errno),
  *         <0 in case of other errors.
@@ -637,3 +641,114 @@ int mnt_context_mount(struct libmnt_context *cxt)
        return rc;
 }
 
+/**
+ * mnt_context_next_mount:
+ * @cxt: context
+ * @itr: iterator
+ * @fs: returns the current filesystem
+ * @mntrc: returns the return code from mnt_mount_context()
+ * @ignored: returns 1 for not matching and 2 for already mounted filesystems
+ *
+ * This function tries to mount the next filesystem from fstab (as returned by
+ * mnt_context_get_fstab()). See also mnt_context_set_fstab().
+ *
+ * You can filter out filesystems by:
+ *     mnt_context_set_options_pattern() to simulate mount -a -O <pattern>
+ *     mnt_context_set_fstype_pattern()  to simulate mount -a -t <pattern>
+ *
+ * If the filesystem is already mounted or does not match defined criteria,
+ * then the mnt_context_next_mount() function returns zero, but the @ignored is
+ * non-zero. Note that the root filesystem and filesystems with "noauto" option
+ * are always ignored.
+ *
+ * If mount(2) syscall or mount.<type> helper failed, then the
+ * mnt_context_next_mount() function returns zero, but the @mntrc is non-zero.
+ * Use also mnt_context_get_status() to check if the filesystem was
+ * successfully mounted.
+ *
+ * Returns: 0 on success,
+ *         <0 in case of error (!= mount(2) errors)
+ *          1 at the end of the list.
+ */
+int mnt_context_next_mount(struct libmnt_context *cxt,
+                          struct libmnt_iter *itr,
+                          struct libmnt_fs **fs,
+                          int *mntrc,
+                          int *ignored)
+{
+       struct libmnt_table *fstab, *mtab;
+       const char *o, *tgt;
+       int rc, mounted = 0;
+
+       if (ignored)
+               *ignored = 0;
+       if (mntrc)
+               *mntrc = 0;
+
+       if (!cxt || !fs || !itr)
+               return -EINVAL;
+
+       mtab = cxt->mtab;
+       cxt->mtab = NULL;               /* do not reset mtab */
+       mnt_reset_context(cxt);
+       cxt->mtab = mtab;
+
+       rc = mnt_context_get_fstab(cxt, &fstab);
+       if (rc)
+               return rc;
+
+       rc = mnt_table_next_fs(fstab, itr, fs);
+       if (rc != 0)
+               return rc;      /* more filesystems (or error) */
+
+       o = mnt_fs_get_user_options(*fs);
+       tgt = mnt_fs_get_target(*fs);
+
+       DBG(CXT, mnt_debug_h(cxt, "next-mount: trying %s", tgt));
+
+       /*  ignore swap */
+       if (((*fs)->flags & MNT_FS_SWAP) ||
+
+       /* ignore root filesystem */
+         (tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 0)) ||
+
+       /* ignore noauto filesystems */
+          (o && mnt_optstr_get_option(o, "noauto", NULL, NULL) == 0) ||
+
+       /* ignore filesystems not match with options patterns */
+          (cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
+                                       cxt->fstype_pattern)) ||
+
+       /* ignore filesystems not match with type patterns */
+          (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
+                                       cxt->optstr_pattern))) {
+               if (ignored)
+                       *ignored = 1;
+               DBG(CXT, mnt_debug_h(cxt, "next-mount: not-match "
+                               "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
+                               mnt_fs_get_fstype(*fs),
+                               cxt->fstype_pattern,
+                               mnt_fs_get_options(*fs),
+                               cxt->optstr_pattern));
+               return 0;
+       }
+
+       /* ignore already mounted filesystems */
+       rc = mnt_context_is_fs_mounted(cxt, *fs, &mounted);
+       if (rc)
+               return rc;
+       if (mounted) {
+               if (ignored)
+                       *ignored = 2;
+               return 0;
+       }
+
+       rc = mnt_context_set_fs(cxt, *fs);
+       if (rc)
+               return rc;
+       rc = mnt_context_mount(cxt);
+       if (mntrc)
+               *mntrc = rc;
+       return 0;
+}
+
index a224fb0f848abd6acd2a0204da95d460e0ba7329..111b3a6838d0ef14db60ebc5e982a0c415cb9a80 100644 (file)
@@ -155,7 +155,7 @@ extern int mnt_optstr_append_option(char **optstr, const char *name,
                                const char *value);
 extern int mnt_optstr_prepend_option(char **optstr, const char *name,
                                const char *value);
-extern int mnt_optstr_get_option(char *optstr, const char *name,
+extern int mnt_optstr_get_option(const char *optstr, const char *name,
                                char **value, size_t *valsz);
 extern int mnt_optstr_set_option(char **optstr, const char *name,
                                const char *value);
@@ -395,6 +395,9 @@ extern int mnt_context_is_nomtab(struct libmnt_context *cxt);
 extern int mnt_context_is_force(struct libmnt_context *cxt);
 extern int mnt_context_is_verbose(struct libmnt_context *cxt);
 
+extern int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
+                              struct libmnt_fs *fs, int *mounted);
+
 extern int mnt_context_set_fs(struct libmnt_context *cxt, struct libmnt_fs *fs);
 extern struct libmnt_fs *mnt_context_get_fs(struct libmnt_context *cxt);
 extern int mnt_context_set_source(struct libmnt_context *cxt, const char *source);
@@ -445,6 +448,9 @@ extern int mnt_context_strerror(struct libmnt_context *cxt, char *buf,
 
 extern int mnt_context_mount(struct libmnt_context *cxt);
 extern int mnt_context_umount(struct libmnt_context *cxt);
+extern int mnt_context_next_mount(struct libmnt_context *cxt,
+                          struct libmnt_iter *itr, struct libmnt_fs **fs,
+                          int *mntrc, int *ignored);
 
 extern int mnt_context_prepare_mount(struct libmnt_context *cxt);
 extern int mnt_context_do_mount(struct libmnt_context *cxt);
index d8c01c0187cf32bba9d213ec8ac96c8ec56af312..34727a6685df75b963d13567b8acb09583873923 100644 (file)
@@ -34,12 +34,14 @@ global:
        mnt_context_get_optsmode;
        mnt_context_get_source;
        mnt_context_get_status;
+       mnt_context_get_table;
        mnt_context_get_target;
        mnt_context_get_user_mflags;
        mnt_context_helper_setopt;
        mnt_context_init_helper;
        mnt_context_is_fake;
        mnt_context_is_force;
+       mnt_context_is_fs_mounted;
        mnt_context_is_lazy;
        mnt_context_is_nomtab;
        mnt_context_is_rdonly_umount;
@@ -47,6 +49,7 @@ global:
        mnt_context_is_sloppy;
        mnt_context_is_verbose;
        mnt_context_mount;
+       mnt_context_next_mount;
        mnt_context_prepare_mount;
        mnt_context_prepare_umount;
        mnt_context_set_cache;
@@ -61,19 +64,20 @@ global:
        mnt_context_set_optsmode;
        mnt_context_set_source;
        mnt_context_set_syscall_status;
-       mnt_context_get_table;
        mnt_context_set_tables_errcb;
        mnt_context_set_target;
        mnt_context_set_user_mflags;
        mnt_context_strerror;
        mnt_context_umount;
        mnt_copy_fs;
+       mnt_diff_tables;
        mnt_free_cache;
        mnt_free_context;
        mnt_free_fs;
        mnt_free_iter;
        mnt_free_lock;
        mnt_free_mntent;
+       mnt_free_tabdiff;
        mnt_free_table;
        mnt_free_update;
        mnt_fs_append_attributes;
@@ -138,6 +142,7 @@ global:
        mnt_new_fs;
        mnt_new_iter;
        mnt_new_lock;
+       mnt_new_tabdiff;
        mnt_new_table;
        mnt_new_table_from_dir;
        mnt_new_table_from_file;
@@ -160,6 +165,7 @@ global:
        mnt_resolve_spec;
        mnt_resolve_tag;
        mnt_split_optstr;
+       mnt_tabdiff_next_change;
        mnt_table_add_fs;
        mnt_table_find_next_fs;
        mnt_table_find_pair;
@@ -171,6 +177,7 @@ global:
        mnt_table_get_name;
        mnt_table_get_nents;
        mnt_table_get_root_fs;
+       mnt_table_is_fs_mounted;
        mnt_table_next_child_fs;
        mnt_table_next_fs;
        mnt_table_parse_file;
@@ -190,11 +197,6 @@ global:
        mnt_update_is_ready;
        mnt_update_set_fs;
        mnt_update_table;
-       mnt_new_tabdiff;
-       mnt_free_tabdiff;
-       mnt_diff_tables;
-       mnt_tabdiff_next_change;
-       mnt_table_is_fs_mounted;
 local:
        *;
 };
index 406afc4b75ff28de81cf886041c897edaa913d4f..78b7571d24c3c77eb49db10bd80892098663e9cd 100644 (file)
@@ -273,15 +273,15 @@ int mnt_optstr_prepend_option(char **optstr, const char *name, const char *value
  * Returns: 0 on success, 1 when not found the @name or negative number in case
  * of error.
  */
-int mnt_optstr_get_option(char *optstr, const char *name,
-                               char **value, size_t *valsz)
+int mnt_optstr_get_option(const char *optstr, const char *name,
+                         char **value, size_t *valsz)
 {
        struct libmnt_optloc ol;
        int rc;
 
        mnt_init_optloc(&ol);
 
-       rc = mnt_optstr_locate_option(optstr, name, &ol);
+       rc = mnt_optstr_locate_option((char *) optstr, name, &ol);
        if (!rc) {
                if (value)
                        *value = ol.value;