]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: support umount /path/file.img
authorKarel Zak <kzak@redhat.com>
Thu, 12 Jan 2012 20:30:58 +0000 (21:30 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 12 Jan 2012 20:30:58 +0000 (21:30 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context.c
libmount/src/context_umount.c

index d67f692a17ea5ccc4b6d68a563c1b70ec326a4ce..83ce0b994a0f600eee5accb174ba31615e0dcfc9 100644 (file)
@@ -1185,7 +1185,7 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
        }
 
        if (rc)
-               DBG(CXT, mnt_debug_h(cxt, "failed to prepare target"));
+               DBG(CXT, mnt_debug_h(cxt, "failed to prepare target '%s'", tgt));
        else
                DBG(CXT, mnt_debug_h(cxt, "final target '%s'",
                                        mnt_fs_get_target(cxt->fs)));
index 568cf505ba5e86cdbcc42aa456fc1090cab13d7c..9d7701f6edfed38b0189d146b0d4cb1fd0d35964 100644 (file)
@@ -15,6 +15,7 @@
 #include <sys/mount.h>
 
 #include "pathnames.h"
+#include "loopdev.h"
 #include "strutils.h"
 #include "mountP.h"
 
@@ -40,7 +41,7 @@
 
 static int lookup_umount_fs(struct libmnt_context *cxt)
 {
-       int rc;
+       int rc, loopdev = 0;
        const char *tgt;
        struct libmnt_table *mtab = NULL;
        struct libmnt_fs *fs;
@@ -60,6 +61,8 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
                DBG(CXT, mnt_debug_h(cxt, "umount: failed to read mtab"));
                return rc;
        }
+
+try_loopdev:
        fs = mnt_table_find_target(mtab, tgt, MNT_ITER_BACKWARD);
        if (!fs) {
                /* maybe the option is source rather than target (mountpoint) */
@@ -85,6 +88,34 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
                }
        }
 
+       if (!fs && !loopdev) {
+               /*
+                * Maybe target is /path/file.img, try to convert to /dev/loopN
+                */
+               struct stat st;
+
+               if (stat(tgt, &st) == 0 && S_ISREG(st.st_mode)) {
+                       char *dev = NULL;
+                       int count = loopdev_count_by_backing_file(tgt, &dev);
+
+                       if (count == 1) {
+                               DBG(CXT, mnt_debug_h(cxt,
+                                       "umount: %s --> %s (retry)", tgt, dev));
+                               mnt_fs_set_source(cxt->fs, tgt);
+                               mnt_fs_set_target(cxt->fs, dev);
+                               free(dev);
+                               tgt = mnt_fs_get_target(cxt->fs);
+
+                               loopdev = 1;            /* to avoid endless loop */
+                               goto try_loopdev;
+
+                       } else if (count > 1)
+                               DBG(CXT, mnt_debug_h(cxt,
+                                       "umount: warning: %s is associated "
+                                       "with more than one loodev", tgt));
+               }
+       }
+
        if (!fs) {
                DBG(CXT, mnt_debug_h(cxt, "umount: cannot find %s in mtab", tgt));
                return 0;
@@ -109,15 +140,14 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
 
 /* check if @devname is loopdev and if the device is associated
  * with a source from @fstab_fs
- *
- * TODO : move this to loopdev.c
  */
-static int mnt_loopdev_associated_fs(const char *devname, struct libmnt_fs *fs)
+static int is_associated_fs(const char *devname, struct libmnt_fs *fs)
 {
        uintmax_t offset = 0;
        const char *src;
        char *val, *optstr;
        size_t valsz;
+       int flags = 0;
 
        /* check if it begins with /dev/loop */
        if (strncmp(devname, _PATH_DEV_LOOP, sizeof(_PATH_DEV_LOOP)))
@@ -131,15 +161,14 @@ static int mnt_loopdev_associated_fs(const char *devname, struct libmnt_fs *fs)
        optstr = (char *) mnt_fs_get_user_options(fs);
 
        if (optstr &&
-           mnt_optstr_get_option(optstr, "offset", &val, &valsz) == 0 &&
-           mnt_parse_offset(val, valsz, &offset) != 0)
-               return 0;
+           mnt_optstr_get_option(optstr, "offset", &val, &valsz) == 0) {
+               flags |= LOOPDEV_FL_OFFSET;
 
-       /* TODO:
-        * if (mnt_loopdev_associated_file(devname, src, offset))
-        *      return 1;
-        */
-       return 0;
+               if (mnt_parse_offset(val, valsz, &offset) != 0)
+                       return 0;
+       }
+
+       return loopdev_is_used(devname, src, offset, flags);
 }
 
 static int prepare_helper_from_options(struct libmnt_context *cxt,
@@ -240,7 +269,7 @@ static int evaluate_permissions(struct libmnt_context *cxt)
                if (fs) {
                        const char *dev = mnt_fs_get_srcpath(cxt->fs);          /* devname from mtab */
 
-                       if (!dev || !mnt_loopdev_associated_fs(dev, fs))
+                       if (!dev || !is_associated_fs(dev, fs))
                                fs = NULL;
                }
                if (!fs) {