aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-03 18:12:29 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-03 18:12:29 +0200
commit72f9464c030c695c94fa0f920d46c38a3e887c61 (patch)
treee9f68421eb1009759635ba7162d256bf201cd6aa
parentcdf61c556f95b0fc8a8ecf187d9f61e60bf99c53 (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.c9
-rw-r--r--bin/gensquashfs/src/glob.c81
-rw-r--r--bin/gensquashfs/test/fstree_glob1.c48
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 {