From b0b88d26c9df6d336167f87ce926bba9b56f6af0 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 25 Mar 2021 14:23:58 +0100 Subject: libfstree: Allow / as argument for "glob" and "dir" commands This allows putting globbed files & directories into the filesystem root, as well as explicitly setting attributes of the root directory from the file lisiting. Signed-off-by: David Oberhollenzer --- lib/fstree/add_by_path.c | 7 ++++- lib/fstree/fstree.c | 1 + lib/fstree/fstree_from_file.c | 26 +++++++++++------ tests/libfstree/Makemodule.am | 1 + tests/libfstree/fstree1.txt | 1 + tests/libfstree/fstree_from_file.c | 3 ++ tests/libfstree/fstree_glob1.c | 59 ++++++++++++++++++++++++++------------ tests/libfstree/fstree_glob3.txt | 2 ++ 8 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 tests/libfstree/fstree_glob3.txt diff --git a/lib/fstree/add_by_path.c b/lib/fstree/add_by_path.c index 7c9063e..8918efc 100644 --- a/lib/fstree/add_by_path.c +++ b/lib/fstree/add_by_path.c @@ -17,6 +17,11 @@ tree_node_t *fstree_add_generic(fstree_t *fs, const char *path, tree_node_t *child, *parent; const char *name; + if (*path == '\0') { + child = fs->root; + goto out; + } + parent = fstree_get_node_by_path(fs, fs->root, path, true, true); if (parent == NULL) return NULL; @@ -27,7 +32,7 @@ tree_node_t *fstree_add_generic(fstree_t *fs, const char *path, child = parent->data.dir.children; while (child != NULL && strcmp(child->name, name) != 0) child = child->next; - +out: if (child != NULL) { if (!S_ISDIR(child->mode) || !S_ISDIR(sb->st_mode) || !child->data.dir.created_implicitly) { diff --git a/lib/fstree/fstree.c b/lib/fstree/fstree.c index b2e199d..7c00755 100644 --- a/lib/fstree/fstree.c +++ b/lib/fstree/fstree.c @@ -120,6 +120,7 @@ int fstree_init(fstree_t *fs, char *defaults) return -1; } + fs->root->data.dir.created_implicitly = true; return 0; } diff --git a/lib/fstree/fstree_from_file.c b/lib/fstree/fstree_from_file.c index dd7ca22..3bf8cd1 100644 --- a/lib/fstree/fstree_from_file.c +++ b/lib/fstree/fstree_from_file.c @@ -344,19 +344,20 @@ static const struct callback_t { unsigned int mode; bool need_extra; bool is_glob; + bool allow_root; int (*callback)(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *sb, const char *basepath, unsigned int glob_flags, const char *extra); } file_list_hooks[] = { - { "dir", S_IFDIR, false, false, add_generic }, - { "slink", S_IFLNK, true, false, add_generic }, - { "link", 0, true, false, add_hard_link }, - { "nod", 0, true, false, add_device }, - { "pipe", S_IFIFO, false, false, add_generic }, - { "sock", S_IFSOCK, false, false, add_generic }, - { "file", S_IFREG, false, false, add_file }, - { "glob", 0, true, true, glob_files }, + { "dir", S_IFDIR, false, false, true, add_generic }, + { "slink", S_IFLNK, true, false, false, add_generic }, + { "link", 0, true, false, false, add_hard_link }, + { "nod", 0, true, false, false, add_device }, + { "pipe", S_IFIFO, false, false, false, add_generic }, + { "sock", S_IFSOCK, false, false, false, add_generic }, + { "file", S_IFREG, false, false, false, add_file }, + { "glob", 0, true, true, true, glob_files }, }; #define NUM_HOOKS (sizeof(file_list_hooks) / sizeof(file_list_hooks[0])) @@ -456,9 +457,12 @@ static int handle_line(fstree_t *fs, const char *filename, if ((line = read_str(line, &path)) == NULL) goto fail_ent; - if (canonicalize_name(path) || *path == '\0') + if (canonicalize_name(path)) goto fail_ent; + if (*path == '\0' && !cb->allow_root) + goto fail_root; + if (cb->is_glob && *line == '*') { ++line; mode = 0; @@ -507,6 +511,10 @@ static int handle_line(fstree_t *fs, const char *filename, return cb->callback(fs, filename, line_num, path, &sb, basepath, glob_flags, extra); +fail_root: + fprintf(stderr, "%s: " PRI_SZ ": cannot use / as argument for %s.\n", + filename, line_num, cb->keyword); + return -1; fail_no_extra: fprintf(stderr, "%s: " PRI_SZ ": missing argument for %s.\n", filename, line_num, cb->keyword); diff --git a/tests/libfstree/Makemodule.am b/tests/libfstree/Makemodule.am index 4dc6da1..8248f5c 100644 --- a/tests/libfstree/Makemodule.am +++ b/tests/libfstree/Makemodule.am @@ -74,3 +74,4 @@ endif EXTRA_DIST += $(FSTDATADIR)/fstree1.txt EXTRA_DIST += $(FSTDATADIR)/fstree_glob1.txt $(FSTDATADIR)/fstree_glob2.txt +EXTRA_DIST += $(FSTDATADIR)/fstree_glob3.txt diff --git a/tests/libfstree/fstree1.txt b/tests/libfstree/fstree1.txt index 090aff9..95ee469 100644 --- a/tests/libfstree/fstree1.txt +++ b/tests/libfstree/fstree1.txt @@ -4,6 +4,7 @@ dir /dir 0755 4 5 nod /chardev 0600 6 7 c 13 37 nod /blkdev 0600 8 9 b 42 21 pipe /pipe 0644 10 11 +dir / 0755 1000 100 dir "/foo bar" 0755 0 0 dir "/foo bar/ test \"/" 0755 0 0 sock /sock 0555 12 13 \ No newline at end of file diff --git a/tests/libfstree/fstree_from_file.c b/tests/libfstree/fstree_from_file.c index c8816e6..5d37960 100644 --- a/tests/libfstree/fstree_from_file.c +++ b/tests/libfstree/fstree_from_file.c @@ -21,6 +21,9 @@ int main(void) n = fs.root->data.dir.children; TEST_EQUAL_UI(fs.root->link_count, 9); + TEST_EQUAL_UI(fs.root->mode, S_IFDIR | 0755); + TEST_EQUAL_UI(fs.root->uid, 1000); + TEST_EQUAL_UI(fs.root->gid, 100); TEST_EQUAL_UI(n->mode, S_IFBLK | 0600); TEST_EQUAL_UI(n->uid, 8); diff --git a/tests/libfstree/fstree_glob1.c b/tests/libfstree/fstree_glob1.c index 592180b..708b0e8 100644 --- a/tests/libfstree/fstree_glob1.c +++ b/tests/libfstree/fstree_glob1.c @@ -9,22 +9,32 @@ #include "fstree.h" #include "../test.h" -static void check_hierarchy(tree_node_t *root, bool recursive) +static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) { - tree_node_t *n, *m; - - n = root->data.dir.children; - TEST_NOT_NULL(n); - TEST_STR_EQUAL(n->name, "tarcorpus"); - TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root); - TEST_NULL(n->next); + tree_node_t *n, *m, *parentdir; + + if (subdir) { + n = root->data.dir.children; + TEST_NOT_NULL(n); + TEST_STR_EQUAL(n->name, "tarcorpus"); + TEST_ASSERT(S_ISDIR(n->mode)); + TEST_ASSERT(n->parent == root); + TEST_NULL(n->next); + } else { + n = root; + TEST_NOT_NULL(n); + TEST_STR_EQUAL(n->name, ""); + TEST_ASSERT(S_ISDIR(n->mode)); + TEST_NULL(n->parent); + TEST_NULL(n->next); + } + parentdir = n; n = n->data.dir.children; TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "file-size"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -43,7 +53,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "format-acceptance"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -68,7 +78,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "large-mtime"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -87,7 +97,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "long-paths"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -106,7 +116,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "negative-mtime"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -125,7 +135,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "sparse-files"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -168,7 +178,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "user-group-largenum"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); if (recursive) { m = n->data.dir.children; @@ -187,7 +197,7 @@ static void check_hierarchy(tree_node_t *root, bool recursive) TEST_NOT_NULL(n); TEST_STR_EQUAL(n->name, "xattr"); TEST_ASSERT(S_ISDIR(n->mode)); - TEST_ASSERT(n->parent == root->data.dir.children); + TEST_ASSERT(n->parent == parentdir); TEST_NULL(n->data.dir.children); n = n->next; @@ -207,7 +217,7 @@ int main(void) TEST_EQUAL_I(ret, 0); fstree_post_process(&fs); - check_hierarchy(fs.root, false); + check_hierarchy(fs.root, true, false); fstree_cleanup(&fs); /* first test case, directory tree plus fnmatch()ed files */ @@ -218,7 +228,18 @@ int main(void) TEST_EQUAL_I(ret, 0); fstree_post_process(&fs); - check_hierarchy(fs.root, true); + check_hierarchy(fs.root, true, true); + fstree_cleanup(&fs); + + /* third test case, same as second, but entries directly at the root */ + ret = fstree_init(&fs, NULL); + TEST_EQUAL_I(ret, 0); + + ret = fstree_from_file(&fs, TEST_PATH "/fstree_glob3.txt", TEST_PATH); + TEST_EQUAL_I(ret, 0); + + fstree_post_process(&fs); + check_hierarchy(fs.root, false, true); fstree_cleanup(&fs); return EXIT_SUCCESS; } diff --git a/tests/libfstree/fstree_glob3.txt b/tests/libfstree/fstree_glob3.txt new file mode 100644 index 0000000..35090e4 --- /dev/null +++ b/tests/libfstree/fstree_glob3.txt @@ -0,0 +1,2 @@ +glob / 0755 0 0 -type d ../libtar/data +glob / 0644 0 0 -type f -name "*gnu*.tar" -- ../libtar/data -- cgit v1.2.3