]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add target prefix support
authorKarel Zak <kzak@redhat.com>
Tue, 22 Oct 2019 11:35:05 +0000 (13:35 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 31 Oct 2019 11:25:08 +0000 (12:25 +0100)
* add set/get functions to context
* use prefix to detect already mounted filesystems
* use prefix when prepare target path

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/docs/libmount-sections.txt
libmount/src/context.c
libmount/src/libmount.h.in
libmount/src/libmount.sym
libmount/src/mountP.h
libmount/src/tab.c

index 95debcfda66476944e2b7067663bf9d5d27266ff..990c0394f2b71adbb674141da02303754dd20070 100644 (file)
@@ -61,6 +61,7 @@ mnt_context_get_syscall_errno
 mnt_context_get_table
 mnt_context_get_target
 mnt_context_get_target_ns
+mnt_context_get_target_prefix
 mnt_context_get_user_mflags
 mnt_context_helper_executed
 mnt_context_helper_setopt
@@ -99,6 +100,7 @@ mnt_context_set_syscall_status
 mnt_context_set_tables_errcb
 mnt_context_set_target
 mnt_context_set_target_ns
+mnt_context_set_target_prefix
 mnt_context_set_user_mflags
 mnt_context_strerror
 mnt_context_switch_ns
index af9b9ca50c1b516e6b31d188808180ccee28c497..bca0b4ca5568c643322b57ce578f86f340218299 100644 (file)
@@ -95,6 +95,7 @@ void mnt_free_context(struct libmnt_context *cxt)
 
        free(cxt->fstype_pattern);
        free(cxt->optstr_pattern);
+       free(cxt->tgt_prefix);
 
        mnt_unref_table(cxt->fstab);
        mnt_unref_cache(cxt->cache);
@@ -118,7 +119,7 @@ void mnt_free_context(struct libmnt_context *cxt)
  * Resets all information in the context that is directly related to
  * the latest mount (spec, source, target, mount options, ...).
  *
- * The match patterns, target namespace, cached fstab, cached canonicalized
+ * The match patterns, target namespace, prefix, cached fstab, cached canonicalized
  * paths and tags and [e]uid are not reset. You have to use
  *
  *     mnt_context_set_fstab(cxt, NULL);
@@ -217,6 +218,8 @@ struct libmnt_context *mnt_copy_context(struct libmnt_context *o)
        n->mtab = o->utab;
        mnt_ref_table(n->utab);
 
+       if (o->tgt_prefix)
+               n->tgt_prefix = strdup(o->tgt_prefix);
        if (o->helper)
                n->helper = strdup(o->helper);
        if (o->orig_user)
@@ -929,6 +932,42 @@ const char *mnt_context_get_target(struct libmnt_context *cxt)
        return mnt_fs_get_target(mnt_context_get_fs(cxt));
 }
 
+/**
+ * mnt_context_set_target_prefix:
+ * @cxt: mount context
+ * @path: mountpoint prefix
+ *
+ * Returns: 0 on success, negative number in case of error.
+ */
+int mnt_context_set_target_prefix(struct libmnt_context *cxt, const char *path)
+{
+       char *p = NULL;
+
+       if (!cxt)
+               return -EINVAL;
+       if (path) {
+               p = strdup(path);
+               if (!p)
+                       return -ENOMEM;
+       }
+       free(cxt->tgt_prefix);
+       cxt->tgt_prefix = p;
+
+       return 0;
+}
+
+/**
+ * mnt_context_get_target_prefix:
+ * @cxt: mount context
+ *
+ * Returns: returns pointer or NULL in case of error or if not set.
+ */
+const char *mnt_context_get_target_prefix(struct libmnt_context *cxt)
+{
+       return cxt ? cxt->tgt_prefix : NULL;
+}
+
+
 /**
  * mnt_context_set_fstype:
  * @cxt: mount context
@@ -1758,7 +1797,7 @@ static int mkdir_target(const char *tgt, struct libmnt_fs *fs)
 
 int mnt_context_prepare_target(struct libmnt_context *cxt)
 {
-       const char *tgt;
+       const char *tgt, *prefix;
        struct libmnt_cache *cache;
        int rc = 0;
        struct libmnt_ns *ns_old;
@@ -1773,6 +1812,29 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
        if (!tgt)
                return 0;
 
+       /* apply prefix */
+       prefix = mnt_context_get_target_prefix(cxt);
+       if (prefix) {
+               const char *p = *tgt == '/' ? tgt + 1 : tgt;
+
+               if (!*p)
+                       /* target is "/", use "/prefix" */
+                       rc = mnt_fs_set_target(cxt->fs, prefix);
+               else {
+                       char *path = NULL;
+
+                       if (asprintf(&path, "%s/%s", prefix, p) <= 0)
+                               rc = -ENOMEM;
+                       else {
+                               rc = mnt_fs_set_target(cxt->fs, path);
+                               free(path);
+                       }
+               }
+               if (rc)
+                       return rc;
+               tgt = mnt_fs_get_target(cxt->fs);
+       }
+
        ns_old = mnt_context_switch_target_ns(cxt);
        if (!ns_old)
                return -MNT_ERR_NAMESPACE;
@@ -2660,7 +2722,8 @@ int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
        } else if (rc)
                return rc;
 
-       *mounted = mnt_table_is_fs_mounted(mtab, fs);
+       *mounted = __mnt_table_is_fs_mounted(mtab, fs,
+                               mnt_context_get_target_prefix(cxt));
 
        if (!mnt_context_switch_ns(cxt, ns_old))
                return -MNT_ERR_NAMESPACE;
index 19535bd7ff94d85aee275b778f49b9482f6c3556..19d4c5b53cd1fb5bdfe4ac0981db9e88828218ee 100644 (file)
@@ -772,10 +772,12 @@ 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);
 extern int mnt_context_set_target(struct libmnt_context *cxt, const char *target);
 extern int mnt_context_set_fstype(struct libmnt_context *cxt, const char *fstype);
+extern int mnt_context_set_target_prefix(struct libmnt_context *cxt, const char *path);
 
 extern const char *mnt_context_get_source(struct libmnt_context *cxt);
 extern const char *mnt_context_get_target(struct libmnt_context *cxt);
 extern const char *mnt_context_get_fstype(struct libmnt_context *cxt);
+extern const char *mnt_context_get_target_prefix(struct libmnt_context *cxt);
 
 extern void *mnt_context_get_mtab_userdata(struct libmnt_context *cxt);
 extern void *mnt_context_get_fstab_userdata(struct libmnt_context *cxt);
index b7731b517a11680169564809a1e8599fd9eaa364..b9a4c0d22dff4361f56c67be1db332aeb8e6c280 100644 (file)
@@ -350,3 +350,8 @@ MOUNT_2.34 {
        mnt_table_insert_fs;
        mnt_table_move_fs;
 } MOUNT_2.33;
+
+MOUNT_2_35 {
+       mnt_context_get_target_prefix;
+       mnt_context_set_target_prefix;
+} MOUNT_2.34;
index 6f283965c0ff306f8437567fc14acd394d17d74f..4ba1308796359c4e5bb7538f7d46274ace47c543 100644 (file)
@@ -139,6 +139,10 @@ extern struct libmnt_fs *mnt_table_get_fs_root(struct libmnt_table *tb,
                                        unsigned long mountflags,
                                        char **fsroot);
 
+extern int __mnt_table_is_fs_mounted(  struct libmnt_table *tb,
+                                       struct libmnt_fs *fstab_fs,
+                                       const char *tgt_prefix);
+
 /*
  * Generic iterator
  */
@@ -325,6 +329,8 @@ struct libmnt_context
        const char      *utab_path; /* path to utab */
        int             utab_writable; /* is utab writable */
 
+       char            *tgt_prefix;    /* path used for all targets */
+
        int     flags;          /* private context flags */
 
        char    *helper;        /* name of the used /sbin/[u]mount.<type> helper */
index ff1997e837a3faecfe5454fa6cd3a06430dba159..2218285b4cbe41316928fd155ba3afae307a34ce 100644 (file)
@@ -1653,27 +1653,9 @@ err:
        return NULL;
 }
 
-/**
- * mnt_table_is_fs_mounted:
- * @tb: /proc/self/mountinfo file
- * @fstab_fs: /etc/fstab entry
- *
- * Checks if the @fstab_fs entry is already in the @tb table. The "swap" is
- * ignored. This function explicitly compares the source, target and root of the
- * filesystems.
- *
- * Note that source and target are canonicalized only if a cache for @tb is
- * defined (see mnt_table_set_cache()). The target canonicalization may
- * trigger automount on autofs mountpoints!
- *
- * Don't use it if you want to know if a device is mounted, just use
- * mnt_table_find_source() on the device.
- *
- * This function is designed mostly for "mount -a".
- *
- * Returns: 0 or 1
- */
-int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
+
+int __mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs,
+                             const char *tgt_prefix)
 {
        struct libmnt_iter itr;
        struct libmnt_fs *fs;
@@ -1681,7 +1663,7 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
        char *root = NULL;
        char *src2 = NULL;
        const char *src = NULL, *tgt = NULL;
-       char *xtgt = NULL;
+       char *xtgt = NULL, *tgt_buf = NULL;
        int rc = 0;
        dev_t devno = 0;
 
@@ -1799,6 +1781,19 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
                 * mountpoints.
                 */
                if (!xtgt) {
+                       if (tgt_prefix) {
+                               const char *p = *tgt == '/' ? tgt + 1 : tgt;
+                               if (!*p)
+                                       tgt = tgt_prefix;       /* target is '/' */
+                               else {
+                                       if (asprintf(&tgt_buf, "%s/%s", tgt_prefix, p) <= 0) {
+                                               rc = -ENOMEM;
+                                               goto done;
+                                       }
+                                       tgt = tgt_buf;
+                               }
+                       }
+
                        if (mnt_fs_streq_target(fs, tgt))
                                break;
                        if (tb->cache)
@@ -1812,12 +1807,39 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
                rc = 1;         /* success */
 done:
        free(root);
+       free(tgt_buf);
 
        DBG(TAB, ul_debugobj(tb, "mnt_table_is_fs_mounted: %s [rc=%d]", src, rc));
        free(src2);
        return rc;
 }
 
+/**
+ * mnt_table_is_fs_mounted:
+ * @tb: /proc/self/mountinfo file
+ * @fstab_fs: /etc/fstab entry
+ *
+ * Checks if the @fstab_fs entry is already in the @tb table. The "swap" is
+ * ignored. This function explicitly compares the source, target and root of the
+ * filesystems.
+ *
+ * Note that source and target are canonicalized only if a cache for @tb is
+ * defined (see mnt_table_set_cache()). The target canonicalization may
+ * trigger automount on autofs mountpoints!
+ *
+ * Don't use it if you want to know if a device is mounted, just use
+ * mnt_table_find_source() on the device.
+ *
+ * This function is designed mostly for "mount -a".
+ *
+ * Returns: 0 or 1
+ */
+int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
+{
+       return __mnt_table_is_fs_mounted(tb, fstab_fs, NULL);
+}
+
+
 #ifdef TEST_PROGRAM
 #include "pathnames.h"