From: Karel Zak Date: Tue, 22 Oct 2019 11:35:05 +0000 (+0200) Subject: libmount: add target prefix support X-Git-Tag: v2.35-rc1~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71ed3b833787160e14744b304f658871a0c836a1;p=thirdparty%2Futil-linux.git libmount: add target prefix support * add set/get functions to context * use prefix to detect already mounted filesystems * use prefix when prepare target path Signed-off-by: Karel Zak --- diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 95debcfda6..990c0394f2 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -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 diff --git a/libmount/src/context.c b/libmount/src/context.c index af9b9ca50c..bca0b4ca55 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -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; diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 19535bd7ff..19d4c5b53c 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -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); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index b7731b517a..b9a4c0d22d 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -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; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 6f283965c0..4ba1308796 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -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. helper */ diff --git a/libmount/src/tab.c b/libmount/src/tab.c index ff1997e837..2218285b4c 100644 --- a/libmount/src/tab.c +++ b/libmount/src/tab.c @@ -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"