diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-09-03 18:12:29 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-09-03 18:12:29 +0200 |
commit | 72f9464c030c695c94fa0f920d46c38a3e887c61 (patch) | |
tree | e9f68421eb1009759635ba7162d256bf201cd6aa | |
parent | cdf61c556f95b0fc8a8ecf187d9f61e60bf99c53 (diff) |
gensquashfs: fix file path for glob directory scanning
If we glob a directory, the generated entries can be added to a
virtual sub directory, that does not corespond to the original layout.
If we try to use those virtual paths for packing files, it will fail,
so we need to remove that prefix to reconstruct the original path.
Second, the glob operation allows us to select a sub-directory of the
pack-dir. This prefix-path is stripped away when scanning the entries.
We need to add it back to get the original, pack-dir relative file
paths.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | bin/gensquashfs/src/fstree_from_dir.c | 9 | ||||
-rw-r--r-- | bin/gensquashfs/src/glob.c | 81 | ||||
-rw-r--r-- | bin/gensquashfs/test/fstree_glob1.c | 48 |
3 files changed, 128 insertions, 10 deletions
diff --git a/bin/gensquashfs/src/fstree_from_dir.c b/bin/gensquashfs/src/fstree_from_dir.c index cbdc270..defc8bf 100644 --- a/bin/gensquashfs/src/fstree_from_dir.c +++ b/bin/gensquashfs/src/fstree_from_dir.c @@ -21,15 +21,6 @@ int fstree_from_dir(fstree_t *fs, sqfs_dir_iterator_t *dir) return -1; } - n = fstree_get_node_by_path(fs, fs->root, ent->name, - false, true); - if (n == NULL) { - if (S_ISDIR(ent->mode)) - dir->ignore_subdir(dir); - free(ent); - continue; - } - if (S_ISLNK(ent->mode)) { ret = dir->read_link(dir, &extra); if (ret) { diff --git a/bin/gensquashfs/src/glob.c b/bin/gensquashfs/src/glob.c index dbe93a2..7d37538 100644 --- a/bin/gensquashfs/src/glob.c +++ b/bin/gensquashfs/src/glob.c @@ -63,6 +63,82 @@ static bool set_scan_flag(const char *arg, dir_tree_cfg_t *cfg) return false; } +static int scan_directory(fstree_t *fs, sqfs_dir_iterator_t *dir, + size_t prefix_len, const char *file_prefix) +{ + for (;;) { + sqfs_dir_entry_t *ent = NULL; + tree_node_t *n = NULL; + char *extra = NULL; + + int ret = dir->next(dir, &ent); + if (ret > 0) + break; + if (ret < 0) { + sqfs_perror("readdir", NULL, ret); + return -1; + } + + n = fstree_get_node_by_path(fs, fs->root, ent->name, + false, true); + if (n == NULL) { + if (S_ISDIR(ent->mode)) + dir->ignore_subdir(dir); + free(ent); + continue; + } + + if (S_ISLNK(ent->mode)) { + ret = dir->read_link(dir, &extra); + if (ret) { + free(ent); + sqfs_perror("readlink", ent->name, ret); + return -1; + } + } else if (S_ISREG(ent->mode)) { + const char *src; + + /* skip the prefix, get the name actually + returned by the nested iterator */ + src = ent->name + prefix_len; + while (*src == '/') + ++src; + + /* reconstruct base path relative file path */ + if (file_prefix == NULL) { + extra = strdup(src); + } else { + size_t fxlen = strlen(file_prefix) + 1; + size_t srclen = strlen(src) + 1; + + extra = malloc(fxlen + srclen); + if (extra != NULL) { + memcpy(extra, file_prefix, fxlen); + memcpy(extra + fxlen, src, srclen); + extra[fxlen - 1] = '/'; + } + } + + if (extra == NULL) { + free(ent); + fputs("out-of-memory\n", stderr); + return -1; + } + } + + n = fstree_add_generic(fs, ent, extra); + free(extra); + free(ent); + + if (n == NULL) { + perror("creating tree node"); + return -1; + } + } + + return 0; +} + int glob_files(fstree_t *fs, const char *filename, size_t line_num, const sqfs_dir_entry_t *ent, const char *basepath, unsigned int glob_flags, @@ -70,6 +146,7 @@ int glob_files(fstree_t *fs, const char *filename, size_t line_num, { bool first_type_flag = true; sqfs_dir_iterator_t *dir = NULL; + const char *file_prefix = NULL; char *prefix = NULL; dir_tree_cfg_t cfg; tree_node_t *root; @@ -155,12 +232,14 @@ int glob_files(fstree_t *fs, const char *filename, size_t line_num, dir = dir_tree_iterator_create(temp, &cfg); free(temp); + + file_prefix = sep->args[0]; } if (dir == NULL) goto fail; - ret = fstree_from_dir(fs, dir); + ret = scan_directory(fs, dir, strlen(cfg.prefix), file_prefix); sqfs_drop(dir); free(prefix); diff --git a/bin/gensquashfs/test/fstree_glob1.c b/bin/gensquashfs/test/fstree_glob1.c index f7a61e0..315ab74 100644 --- a/bin/gensquashfs/test/fstree_glob1.c +++ b/bin/gensquashfs/test/fstree_glob1.c @@ -43,6 +43,10 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/file-size/gnu.tar"); + m = m->next; TEST_NULL(m); } else { @@ -62,12 +66,20 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/format-acceptance/gnu-g.tar"); + m = m->next; TEST_NOT_NULL(m); TEST_STR_EQUAL(m->name, "gnu.tar"); TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/format-acceptance/gnu.tar"); + m = m->next; TEST_NULL(m); } else { @@ -94,6 +106,10 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/large-mtime/gnu.tar"); + m = m->next; TEST_NULL(m); } else { @@ -113,6 +129,10 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/long-paths/gnu.tar"); + m = m->next; TEST_NULL(m); } else { @@ -132,6 +152,10 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/negative-mtime/gnu.tar"); + m = m->next; TEST_NULL(m); } else { @@ -151,30 +175,50 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/sparse-files/gnu-small.tar"); + m = m->next; TEST_NOT_NULL(m); TEST_STR_EQUAL(m->name, "gnu.tar"); TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/sparse-files/gnu.tar"); + m = m->next; TEST_NOT_NULL(m); TEST_STR_EQUAL(m->name, "pax-gnu0-0.tar"); TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/sparse-files/pax-gnu0-0.tar"); + m = m->next; TEST_NOT_NULL(m); TEST_STR_EQUAL(m->name, "pax-gnu0-1.tar"); TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/sparse-files/pax-gnu0-1.tar"); + m = m->next; TEST_NOT_NULL(m); TEST_STR_EQUAL(m->name, "pax-gnu1-0.tar"); TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/sparse-files/pax-gnu1-0.tar"); + m = m->next; TEST_NULL(m); } else { @@ -194,6 +238,10 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive) TEST_ASSERT(S_ISREG(m->mode)); TEST_ASSERT(m->parent == n); + TEST_NOT_NULL(m->data.file.input_file); + TEST_STR_EQUAL(m->data.file.input_file, + "../../../lib/tar/test/data/user-group-largenum/gnu.tar"); + m = m->next; TEST_NULL(m); } else { |