From: Karel Zak Date: Mon, 25 Mar 2013 12:56:31 +0000 (+0100) Subject: libmount: add mnt_table_find_mountpoint() X-Git-Tag: v2.23-rc2~123 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dcc15ce5afc7a5f86f65f9084a780f9509e15613;p=thirdparty%2Futil-linux.git libmount: add mnt_table_find_mountpoint() This is more robust implementation of mnt_get_mountpoint() that does not ignore bind mountpoints (mount --bind /mnt /mnt) as it does not depend on st_dev numbers. Signed-off-by: Karel Zak --- diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 3475630d70..2c3dab7225 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -283,6 +283,7 @@ mnt_new_table_from_dir mnt_new_table_from_file mnt_table_add_fs mnt_table_find_devno +mnt_table_find_mountpoint mnt_table_find_next_fs mnt_table_find_pair mnt_table_find_source diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 739f5daee6..1b5df82ac8 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -462,6 +462,8 @@ extern int mnt_table_get_root_fs(struct libmnt_table *tb, struct libmnt_fs **roo extern int mnt_table_set_iter(struct libmnt_table *tb, struct libmnt_iter *itr, struct libmnt_fs *fs); +extern struct libmnt_fs *mnt_table_find_mountpoint(struct libmnt_table *tb, + const char *path, int direction); extern struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *path, int direction); extern struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 9fc0ee6b0e..2ea4839894 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -254,4 +254,5 @@ global: mnt_fs_get_optional_fields; mnt_fs_get_propagation; mnt_context_find_umount_fs; + mnt_table_find_mountpoint; } MOUNT_2.22; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 1b4ba687bd..065b815c19 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -132,6 +132,8 @@ extern int endswith(const char *s, const char *sx) extern int startswith(const char *s, const char *sx) __attribute__((nonnull)); +extern char *stripoff_last_component(char *path); + extern int is_file_empty(const char *name); extern int mkdir_p(const char *path, mode_t mode); diff --git a/libmount/src/tab.c b/libmount/src/tab.c index 5287da4a50..f70ed7de08 100644 --- a/libmount/src/tab.c +++ b/libmount/src/tab.c @@ -425,6 +425,51 @@ int mnt_table_set_iter(struct libmnt_table *tb, struct libmnt_iter *itr, struct return 0; } +/** + * mnt_table_find_mountpoint: + * @tb: tab pointer + * @path: directory + * @direction: MNT_ITER_{FORWARD,BACKWARD} + * + * Same like mnt_get_mountpoint(), but this function does not rely on + * st_dev numbers. + * + * Returns: a tab entry or NULL. + */ +struct libmnt_fs *mnt_table_find_mountpoint(struct libmnt_table *tb, + const char *path, + int direction) +{ + char *mnt; + + if (!tb || !path) + return NULL; + + DBG(TAB, mnt_debug_h(tb, "lookup MOUNTPOINT: %s", path)); + + mnt = strdup(path); + if (!mnt) + return NULL; + + do { + char *p; + struct libmnt_fs *fs; + + fs = mnt_table_find_target(tb, mnt, direction); + if (fs) { + free(mnt); + return fs; + } + + p = stripoff_last_component(mnt); + if (!p || !*p) + break; + } while (mnt && *(mnt + 1) != '\0'); + + free(mnt); + return mnt_table_find_target(tb, "/", direction); +} + /** * mnt_table_find_target: * @tb: tab pointer @@ -517,6 +562,8 @@ struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *pa const char *p; assert(tb); + if (!tb || !path) + return NULL; DBG(TAB, mnt_debug_h(tb, "lookup srcpath: %s", path)); @@ -1009,6 +1056,7 @@ done: } #ifdef TEST_PROGRAM +#include "pathnames.h" static int parser_errcb(struct libmnt_table *tb, const char *filename, int line) { @@ -1171,6 +1219,33 @@ done: return rc; } +int test_find_mountpoint(struct libmnt_test *ts, int argc, char *argv[]) +{ + struct libmnt_table *tb; + struct libmnt_fs *fs; + struct libmnt_cache *mpc = NULL; + int rc = -1; + + tb = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); + if (!tb) + return -1; + mpc = mnt_new_cache(); + if (!mpc) + goto done; + mnt_table_set_cache(tb, mpc); + + fs = mnt_table_find_mountpoint(tb, argv[1], MNT_ITER_BACKWARD); + if (!fs) + goto done; + + mnt_fs_print_debug(fs, stdout); + rc = 0; +done: + mnt_free_table(tb); + mnt_free_cache(mpc); + return rc; +} + static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[]) { struct libmnt_table *tb = NULL, *fstab = NULL; @@ -1225,6 +1300,7 @@ int main(int argc, char *argv[]) { "--find-forward", test_find_fw, " " }, { "--find-backward", test_find_bw, " " }, { "--find-pair", test_find_pair, " " }, + { "--find-mountpoint", test_find_mountpoint, "" }, { "--copy-fs", test_copy_fs, " copy root FS from the file" }, { "--is-mounted", test_is_mounted, " check what from are already mounted" }, { NULL } diff --git a/libmount/src/utils.c b/libmount/src/utils.c index 1d4fd0e4b3..5453789e32 100644 --- a/libmount/src/utils.c +++ b/libmount/src/utils.c @@ -94,7 +94,7 @@ static int fstype_cmp(const void *v1, const void *v2) /* returns basename and keeps dirname in the @path, if @path is "/" (root) * then returns empty string */ -static char *stripoff_last_component(char *path) +char *stripoff_last_component(char *path) { char *p = path ? strrchr(path, '/') : NULL;