]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add mnt_context_umount_next()
authorKarel Zak <kzak@redhat.com>
Thu, 1 Dec 2011 15:45:53 +0000 (16:45 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 1 Dec 2011 15:45:53 +0000 (16:45 +0100)
This is "umount -a" backend.

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context.c
libmount/src/context_umount.c
libmount/src/libmount.h.in
libmount/src/libmount.sym

index dadde5c892a7eed3c702236f880351f987e9a2f2..e971003cb20a9a9046dcd9debf8cf3ef2670440d 100644 (file)
@@ -1358,7 +1358,7 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
 
        if (cxt->action == MNT_ACT_UMOUNT)
                rc = mnt_update_set_fs(cxt->update, cxt->mountflags,
-                                       mnt_fs_get_target(cxt->fs), NULL);
+                                       mnt_context_get_target(cxt), NULL);
        else
                rc = mnt_update_set_fs(cxt->update, cxt->mountflags,
                                        NULL, cxt->fs);
index 3486ef5432314a467da28303dd6810df7721fef5..5474da01d8e91829dbf28532582fb35c24ccb1b7 100644 (file)
@@ -90,17 +90,19 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
                return 0;
        }
 
-       /* copy from mtab to our FS description
-        */
-       mnt_fs_set_source(cxt->fs, NULL);
-       mnt_fs_set_target(cxt->fs, NULL);
+       if (fs != cxt->fs) {
+               /* copy from mtab to our FS description
+                */
+               mnt_fs_set_source(cxt->fs, NULL);
+               mnt_fs_set_target(cxt->fs, NULL);
 
-       if (!mnt_copy_fs(cxt->fs, fs)) {
-               DBG(CXT, mnt_debug_h(cxt, "umount: failed to copy FS"));
-               return -errno;
+               if (!mnt_copy_fs(cxt->fs, fs)) {
+                       DBG(CXT, mnt_debug_h(cxt, "umount: failed to copy FS"));
+                       return -errno;
+               }
+               DBG(CXT, mnt_debug_h(cxt, "umount: mtab applied"));
        }
 
-       DBG(CXT, mnt_debug_h(cxt, "umount: mtab applied"));
        cxt->flags |= MNT_FL_TAB_APPLIED;
        return rc;
 }
@@ -464,12 +466,9 @@ static int do_umount(struct libmnt_context *cxt)
        if (!target)
                return -EINVAL;
 
-       if (cxt->flags & MNT_FL_FAKE)
-               return 0;
-
        DBG(CXT, mnt_debug_h(cxt, "do umount"));
 
-       if (cxt->restricted) {
+       if (cxt->restricted && !(cxt->flags & MNT_FL_FAKE)) {
                /*
                 * extra paranoa for non-root users
                 * -- chdir to the parent of the mountpoint and use NOFOLLOW
@@ -490,14 +489,18 @@ static int do_umount(struct libmnt_context *cxt)
        else if (cxt->flags & MNT_FL_FORCE)
                flags |= MNT_FORCE;
 
-       DBG(CXT, mnt_debug_h(cxt, "umount(2) [target='%s', flags=0x%08x]",
-                               target, flags));
-
-       rc = flags ? umount2(target, flags) : umount(target);
-       if (rc < 0)
-               cxt->syscall_status = -errno;
+       DBG(CXT, mnt_debug_h(cxt, "umount(2) [target='%s', flags=0x%08x]%s",
+                               target, flags,
+                               cxt->flags & MNT_FL_FAKE ? " (FAKE)" : ""));
 
-       free(tgtbuf);
+       if (cxt->flags & MNT_FL_FAKE)
+               rc = 0;
+       else {
+               rc = flags ? umount2(target, flags) : umount(target);
+               if (rc < 0)
+                       cxt->syscall_status = -errno;
+               free(tgtbuf);
+       }
 
        /*
         * try remount read-only
@@ -556,7 +559,7 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt)
 
        if (!cxt || !cxt->fs || (cxt->fs->flags & MNT_FS_SWAP))
                return -EINVAL;
-       if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs))
+       if (!mnt_context_get_source(cxt) && !mnt_context_get_target(cxt))
                return -EINVAL;
        if (cxt->flags & MNT_FL_PREPARED)
                return 0;
@@ -719,6 +722,8 @@ int mnt_context_umount(struct libmnt_context *cxt)
        assert(cxt->helper_exec_status == 1);
        assert(cxt->syscall_status == 1);
 
+       DBG(CXT, mnt_debug_h(cxt, "umount: %s", mnt_context_get_target(cxt)));
+
        rc = mnt_context_prepare_umount(cxt);
        if (!rc)
                rc = mnt_context_prepare_update(cxt);
@@ -728,3 +733,95 @@ int mnt_context_umount(struct libmnt_context *cxt)
                rc = mnt_context_update_tabs(cxt);
        return rc;
 }
+
+
+/**
+ * mnt_context_next_umount:
+ * @cxt: context
+ * @itr: iterator
+ * @fs: returns the current filesystem
+ * @mntrc: returns the return code from mnt_context_umount()
+ * @ignored: returns 1 for not matching
+ *
+ * This function tries to umount the next filesystem from mtab (as returned by
+ * mnt_context_get_mtab()).
+ *
+ * You can filter out filesystems by:
+ *     mnt_context_set_options_pattern() to simulate umount -a -O pattern
+ *     mnt_context_set_fstype_pattern()  to simulate umount -a -t pattern
+ *
+ * If the filesystem is not mounted or does not match defined criteria,
+ * then the function mnt_context_next_umount() returns zero, but the @ignored is
+ * non-zero. Note that the root filesystem is always ignored.
+ *
+ * If umount(2) syscall or umount.type helper failed, then the
+ * mnt_context_next_umount() function returns zero, but the @mntrc is non-zero.
+ * Use also mnt_context_get_status() to check if the filesystem was
+ * successfully umounted.
+ *
+ * Returns: 0 on success,
+ *         <0 in case of error (!= umount(2) errors)
+ *          1 at the end of the list.
+ */
+int mnt_context_next_umount(struct libmnt_context *cxt,
+                          struct libmnt_iter *itr,
+                          struct libmnt_fs **fs,
+                          int *mntrc,
+                          int *ignored)
+{
+       struct libmnt_table *mtab;
+       const char *tgt;
+       int rc;
+
+       if (ignored)
+               *ignored = 0;
+       if (mntrc)
+               *mntrc = 0;
+
+       if (!cxt || !fs || !itr)
+               return -EINVAL;
+
+       mnt_context_get_mtab(cxt, &mtab);
+       cxt->mtab = NULL;               /* do not reset mtab */
+       mnt_reset_context(cxt);
+       cxt->mtab = mtab;
+
+       do {
+               rc = mnt_table_next_fs(mtab, itr, fs);
+               if (rc != 0)
+                       return rc;      /* no more filesystems (or error) */
+
+               tgt = mnt_fs_get_target(*fs);
+       } while (!tgt);
+
+       DBG(CXT, mnt_debug_h(cxt, "next-umount: trying %s", tgt));
+
+       /* ignore root filesystem */
+       if ((tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 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-umount: 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;
+       }
+
+       rc = mnt_context_set_fs(cxt, *fs);
+       if (rc)
+               return rc;
+       rc = mnt_context_umount(cxt);
+       if (mntrc)
+               *mntrc = rc;
+       return 0;
+}
index 63923dbc3e37c980c38d7d8098ffb513d25cba05..c991764b9572243c7fb8487cfe1612c83739cf5f 100644 (file)
@@ -456,6 +456,9 @@ 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_next_umount(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 7ae80ce432bdb6b548523df40ff6aa2c465cf2c5..6f4eda71db26b8175f5e09d5190e78f70ec63086 100644 (file)
@@ -205,3 +205,8 @@ global:
        mnt_tabdiff_next_change;
        mnt_table_is_fs_mounted;
 } MOUNT_2.19;
+
+MOUNT_2.21 {
+global:
+       mnt_context_next_umount;
+} MOUNT_2.20;