diff options
-rw-r--r-- | unpack/Makemodule.am | 1 | ||||
-rw-r--r-- | unpack/fill_files.c | 39 | ||||
-rw-r--r-- | unpack/rdsquashfs.c | 21 | ||||
-rw-r--r-- | unpack/rdsquashfs.h | 7 | ||||
-rw-r--r-- | unpack/restore_fstree.c | 71 |
5 files changed, 116 insertions, 23 deletions
diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am index b958851..08a8b76 100644 --- a/unpack/Makemodule.am +++ b/unpack/Makemodule.am @@ -1,6 +1,7 @@ rdsquashfs_SOURCES = unpack/rdsquashfs.c unpack/rdsquashfs.h rdsquashfs_SOURCES += unpack/list_files.c unpack/options.c rdsquashfs_SOURCES += unpack/restore_fstree.c unpack/describe.c +rdsquashfs_SOURCES += unpack/fill_files.c rdsquashfs_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a rdsquashfs_LDADD += $(XZ_LIBS) $(ZLIB_LIBS) $(LZO_LIBS) $(LZ4_LIBS) $(ZSTD_LIBS) diff --git a/unpack/fill_files.c b/unpack/fill_files.c new file mode 100644 index 0000000..6584699 --- /dev/null +++ b/unpack/fill_files.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "config.h" +#include "rdsquashfs.h" + +static int fill_files(data_reader_t *data, file_info_t *list, int flags) +{ + file_info_t *fi; + int fd; + + for (fi = list; fi != NULL; fi = fi->next) { + if (fi->input_file == NULL) + continue; + + fd = open(fi->input_file, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "unpacking %s: %s\n", + fi->input_file, strerror(errno)); + return -1; + } + + if (!(flags & UNPACK_QUIET)) + printf("unpacking %s\n", fi->input_file); + + if (data_reader_dump_file(data, fi, fd, + (flags & UNPACK_NO_SPARSE) == 0)) { + close(fd); + return -1; + } + + close(fd); + } + + return 0; +} + +int fill_unpacked_files(fstree_t *fs, data_reader_t *data, int flags) +{ + return fill_files(data, fs->files, flags); +} diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index 4a0f12b..a3618e3 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -42,6 +42,8 @@ int main(int argc, char **argv) if (deserialize_fstree(&fs, &super, cmp, sqfsfd, opt.rdtree_flags)) goto out_cmp; + fstree_gen_file_list(&fs); + if (opt.cmdpath != NULL) { n = fstree_node_from_path(&fs, opt.cmdpath); if (n == NULL) { @@ -72,11 +74,28 @@ int main(int argc, char **argv) goto out_fs; break; case OP_UNPACK: + if (opt.unpack_root != NULL) { + if (mkdir_p(opt.unpack_root)) + return -1; + + if (pushd(opt.unpack_root)) + return -1; + } + + if (restore_fstree(n, opt.flags)) + goto out_fs; + data = data_reader_create(sqfsfd, &super, cmp); if (data == NULL) goto out_fs; - if (restore_fstree(opt.unpack_root, n, data, opt.flags)) + if (fill_unpacked_files(&fs, data, opt.flags)) + goto out_fs; + + if (update_tree_attribs(n, opt.flags)) + goto out_fs; + + if (opt.unpack_root != NULL && popd() != 0) goto out_fs; break; case OP_DESCRIBE: diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h index ed882ff..45c91db 100644 --- a/unpack/rdsquashfs.h +++ b/unpack/rdsquashfs.h @@ -48,8 +48,11 @@ typedef struct { void list_files(tree_node_t *node); -int restore_fstree(const char *rootdir, tree_node_t *root, - data_reader_t *data, int flags); +int restore_fstree(tree_node_t *root, int flags); + +int update_tree_attribs(tree_node_t *root, int flags); + +int fill_unpacked_files(fstree_t *fs, data_reader_t *data, int flags); void describe_tree(tree_node_t *root, const char *unpack_root); diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c index 455e604..5027625 100644 --- a/unpack/restore_fstree.c +++ b/unpack/restore_fstree.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ #include "rdsquashfs.h" -static int create_node(tree_node_t *n, data_reader_t *data, int flags) +static int create_node(tree_node_t *n, int flags) { tree_node_t *c; char *name; @@ -9,7 +9,7 @@ static int create_node(tree_node_t *n, data_reader_t *data, int flags) if (!(flags & UNPACK_QUIET)) { name = fstree_get_path(n); - printf("unpacking %s\n", name); + printf("creating %s\n", name); free(name); } @@ -25,7 +25,7 @@ static int create_node(tree_node_t *n, data_reader_t *data, int flags) return -1; for (c = n->data.dir->children; c != NULL; c = c->next) { - if (create_node(c, data, flags)) + if (create_node(c, flags)) return -1; } @@ -64,18 +64,45 @@ static int create_node(tree_node_t *n, data_reader_t *data, int flags) return -1; } - if (data_reader_dump_file(data, n->data.file, fd, - (flags & UNPACK_NO_SPARSE) == 0)) { - close(fd); + close(fd); + + if (n->parent != NULL) { + n->data.file->input_file = fstree_get_path(n); + } else { + n->data.file->input_file = strdup(n->name); + } + + if (n->data.file->input_file == NULL) { + perror("restoring file path"); return -1; } - close(fd); + canonicalize_name(n->data.file->input_file); break; default: break; } + return 0; +} + +static int set_attribs(tree_node_t *n, int flags) +{ + tree_node_t *c; + + if (S_ISDIR(n->mode)) { + if (pushd(n->name)) + return -1; + + for (c = n->data.dir->children; c != NULL; c = c->next) { + if (set_attribs(c, flags)) + return -1; + } + + if (popd()) + return -1; + } + if (flags & UNPACK_CHOWN) { if (fchownat(AT_FDCWD, n->name, n->uid, n->gid, AT_SYMLINK_NOFOLLOW)) { @@ -96,28 +123,32 @@ static int create_node(tree_node_t *n, data_reader_t *data, int flags) return 0; } -int restore_fstree(const char *rootdir, tree_node_t *root, - data_reader_t *data, int flags) +int restore_fstree(tree_node_t *root, int flags) { - tree_node_t *n; + tree_node_t *n, *old_parent; - if (rootdir != NULL) { - if (mkdir_p(rootdir)) - return -1; - - if (pushd(rootdir)) - return -1; - } + /* make sure fstree_get_path() stops at this node */ + old_parent = root->parent; + root->parent = NULL; if (S_ISDIR(root->mode)) { for (n = root->data.dir->children; n != NULL; n = n->next) { - if (create_node(n, data, flags)) + if (create_node(n, flags)) return -1; } } else { - if (create_node(root, data, flags)) + if (create_node(root, flags)) return -1; } - return rootdir == NULL ? 0 : popd(); + root->parent = old_parent; + return 0; +} + +int update_tree_attribs(tree_node_t *root, int flags) +{ + if ((flags & (UNPACK_CHOWN | UNPACK_CHMOD)) == 0) + return 0; + + return set_attribs(root, flags); } |