summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--unpack/Makemodule.am1
-rw-r--r--unpack/fill_files.c39
-rw-r--r--unpack/rdsquashfs.c21
-rw-r--r--unpack/rdsquashfs.h7
-rw-r--r--unpack/restore_fstree.c71
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);
}