From 911e694528618b52ce23e4e29a7a85ee9f4edf05 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 21 Feb 2019 13:49:39 +0100 Subject: [PATCH] libmount: add mnt_table_{find,insert,move}_fs() Add functions to insert FS into table to specified position and to move FS between two tables. Co-Author: Tim Hildering Signed-off-by: Karel Zak --- libmount/docs/libmount-sections.txt | 5 +- libmount/src/libmount.h.in | 5 + libmount/src/libmount.sym | 5 +- libmount/src/tab.c | 172 ++++++++++++++++++++++- tests/expected/libmount/tabfiles-find-fs | 1 + tests/ts/libmount/tabfiles | 5 + 6 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 tests/expected/libmount/tabfiles-find-fs diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 3df4a9b0bd..6767b00695 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -329,6 +329,7 @@ mnt_table_append_intro_comment mnt_table_append_trailing_comment mnt_table_enable_comments mnt_table_find_devno +mnt_table_find_fs mnt_table_find_mountpoint mnt_table_find_next_fs mnt_table_find_pair @@ -344,9 +345,11 @@ mnt_table_get_nents mnt_table_get_root_fs mnt_table_get_trailing_comment mnt_table_get_userdata +mnt_table_insert_fs mnt_table_is_empty mnt_table_is_fs_mounted mnt_table_last_fs +mnt_table_move_fs mnt_table_next_child_fs mnt_table_next_fs mnt_table_parse_dir @@ -362,8 +365,8 @@ mnt_table_set_iter mnt_table_set_parser_errcb mnt_table_set_trailing_comment mnt_table_set_userdata -mnt_table_with_comments mnt_table_uniq_fs +mnt_table_with_comments
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index a14bb6f3d1..fb86aaff95 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -560,6 +560,11 @@ extern int mnt_table_append_trailing_comment(struct libmnt_table *tb, const char extern int mnt_table_set_cache(struct libmnt_table *tb, struct libmnt_cache *mpc); extern struct libmnt_cache *mnt_table_get_cache(struct libmnt_table *tb); extern int mnt_table_add_fs(struct libmnt_table *tb, struct libmnt_fs *fs); +extern int mnt_table_find_fs(struct libmnt_table *tb, struct libmnt_fs *fs); +extern int mnt_table_insert_fs(struct libmnt_table *tb, int before, + struct libmnt_fs *pos, struct libmnt_fs *fs); +extern int mnt_table_move_fs(struct libmnt_table *src, struct libmnt_table *dst, + int before, struct libmnt_fs *pos, struct libmnt_fs *fs); extern int mnt_table_remove_fs(struct libmnt_table *tb, struct libmnt_fs *fs); extern int mnt_table_first_fs(struct libmnt_table *tb, struct libmnt_fs **fs); extern int mnt_table_last_fs(struct libmnt_table *tb, struct libmnt_fs **fs); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 0087a3d23b..1d72cf4f7b 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -343,6 +343,9 @@ MOUNT_2.33 { } MOUNT_2.30; MOUNT_2.34 { - mnt_guess_system_root; mnt_context_next_remount; + mnt_guess_system_root; + mnt_table_find_fs; + mnt_table_insert_fs; + mnt_table_move_fs; } MOUNT_2.33; diff --git a/libmount/src/tab.c b/libmount/src/tab.c index 7f08730edc..674dc67e5b 100644 --- a/libmount/src/tab.c +++ b/libmount/src/tab.c @@ -395,6 +395,38 @@ struct libmnt_cache *mnt_table_get_cache(struct libmnt_table *tb) return tb ? tb->cache : NULL; } +/** + * mnt_table_find_fs: + * @tb: tab pointer + * @fs: entry to look for + * + * Checks if @fs is part of table @tb. + * + * Returns: index of @fs in table, 0 if not found or negative number in case of error. + */ +int mnt_table_find_fs(struct libmnt_table *tb, struct libmnt_fs *fs) +{ + struct list_head *p; + int i = 0; + + if (!tb || !fs) + return -EINVAL; + + if (list_empty(&fs->ents)) + return 0; + + /* Let's use directly list rather than mnt_table_next_fs() as we + * compare list entry with fs only. + */ + list_for_each(p, &tb->ents) { + ++i; + if (list_entry(p, struct libmnt_fs, ents) == fs) + return i; + } + + return 0; +} + /** * mnt_table_add_fs: * @tb: tab pointer @@ -423,6 +455,95 @@ int mnt_table_add_fs(struct libmnt_table *tb, struct libmnt_fs *fs) return 0; } +static int __table_insert_fs( + struct libmnt_table *tb, int before, + struct libmnt_fs *pos, struct libmnt_fs *fs) +{ + struct list_head *head = pos ? &pos->ents : &tb->ents; + + if (before) + list_add(&fs->ents, head); + else + list_add_tail(&fs->ents, head); + + tb->nents++; + + DBG(TAB, ul_debugobj(tb, "insert entry: %s %s", + mnt_fs_get_source(fs), mnt_fs_get_target(fs))); + return 0; +} + +/** + * mnt_table_insert_fs: + * @tb: tab pointer + * @before: 1 to insert before pos, 0 to insert after pos + * @pos: entry to specify position or NULL + * @fs: new entry + * + * Adds a new entry to @tb before or after a specific table entry @pos. If the + * @pos is NULL than add the begin of the @tab if @before is 1; or to the tail + * of the @tb if @before is 0. + * + * This function inncrements reference to @fs. Don't forget to use + * mnt_unref_fs() after mnt_table_insert_fs() if you want to keep the @fs + * referenced by the table only. + + * + * Returns: 0 on success or negative number in case of error. + */ +int mnt_table_insert_fs(struct libmnt_table *tb, int before, + struct libmnt_fs *pos, struct libmnt_fs *fs) +{ + if (!tb || !fs) + return -EINVAL; + + if (!list_empty(&fs->ents)) + return -EBUSY; + + if (pos && mnt_table_find_fs(tb, pos) < 1) + return -ENOENT; + + mnt_ref_fs(fs); + return __table_insert_fs(tb, before, pos, fs); +} + +/** + * mnt_table_move_fs: + * @src: tab pointer of source table + * @dst: tab pointer of destination table + * @before: 1 to move before position, 0 to move after position + * @pos: entry to specify position or NULL + * @fs: entry to move + * + * Removes @fs from @src table and adds it before/after a specific entry @pos + * of @dst table. If the @pos is NULL than add the begin of the @dst if @before + * is 1; or to the tail of the @dst if @before is 0. + * + * The reference counter of @fs is not modified. + * + * Returns: 0 on success or negative number in case of error. + */ +int mnt_table_move_fs(struct libmnt_table *src, struct libmnt_table *dst, + int before, struct libmnt_fs *pos, struct libmnt_fs *fs) +{ + if (!src || !dst || !fs) + return -EINVAL; + + if (mnt_table_find_fs(src, fs) < 1) + return -ENOENT; + + if (pos && mnt_table_find_fs(dst, pos) < 1) + return -ENOENT; + + /* remove from source */ + list_del_init(&fs->ents); + src->nents--; + + /* insert to the destination */ + return __table_insert_fs(dst, before, pos, fs); +} + + /** * mnt_table_remove_fs: * @tb: tab pointer @@ -436,11 +557,10 @@ int mnt_table_add_fs(struct libmnt_table *tb, struct libmnt_fs *fs) */ int mnt_table_remove_fs(struct libmnt_table *tb, struct libmnt_fs *fs) { - if (!tb || !fs) + if (!tb || !fs || mnt_table_find_fs(tb, fs) < 1) return -EINVAL; - list_del(&fs->ents); - INIT_LIST_HEAD(&fs->ents); /* otherwise FS still points to the list */ + list_del_init(&fs->ents); mnt_unref_fs(fs); tb->nents--; @@ -1788,6 +1908,51 @@ done: return rc; } +static int test_find_idx(struct libmnt_test *ts, int argc, char *argv[]) +{ + struct libmnt_table *tb; + struct libmnt_fs *fs = NULL; + struct libmnt_cache *mpc = NULL; + const char *file, *what; + int rc = -1; + + if (argc != 3) { + fprintf(stderr, "try --help\n"); + return -EINVAL; + } + + file = argv[1], what = argv[2]; + + tb = create_table(file, FALSE); + if (!tb) + goto done; + + /* create a cache for canonicalized paths */ + mpc = mnt_new_cache(); + if (!mpc) + goto done; + mnt_table_set_cache(tb, mpc); + mnt_unref_cache(mpc); + + fs = mnt_table_find_target(tb, what, MNT_ITER_BACKWARD); + + if (!fs) + fprintf(stderr, "%s: not found '%s'\n", file, what); + else { + int idx = mnt_table_find_fs(tb, fs); + + if (idx < 1) + fprintf(stderr, "%s: not found '%s' fs pointer", file, what); + else { + printf("%s index is %d\n", what, idx); + rc = 0; + } + } +done: + mnt_unref_table(tb); + return rc; +} + static int test_find(struct libmnt_test *ts, int argc, char *argv[], int dr) { struct libmnt_table *tb; @@ -1994,6 +2159,7 @@ int main(int argc, char *argv[]) { "--find-backward", test_find_bw, " " }, { "--uniq-target", test_uniq, "" }, { "--find-pair", test_find_pair, " " }, + { "--find-fs", test_find_idx, " " }, { "--find-mountpoint", test_find_mountpoint, "" }, { "--copy-fs", test_copy_fs, " copy root FS from the file" }, { "--is-mounted", test_is_mounted, " check what from fstab is already mounted" }, diff --git a/tests/expected/libmount/tabfiles-find-fs b/tests/expected/libmount/tabfiles-find-fs new file mode 100644 index 0000000000..0c67fb8f21 --- /dev/null +++ b/tests/expected/libmount/tabfiles-find-fs @@ -0,0 +1 @@ +/home/kzak index is 27 diff --git a/tests/ts/libmount/tabfiles b/tests/ts/libmount/tabfiles index ec0eae8e14..716fed8cb2 100755 --- a/tests/ts/libmount/tabfiles +++ b/tests/ts/libmount/tabfiles @@ -77,4 +77,9 @@ ts_run $TESTPROG --find-pair "$TS_SELF/files/mtab" /dev/mapper/kzak-home /home/k sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT ts_finalize_subtest +ts_init_subtest "find-fs" +ts_run $TESTPROG --find-fs "$TS_SELF/files/mountinfo" /home/kzak &> $TS_OUTPUT +sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT +ts_finalize_subtest + ts_finalize -- 2.39.2