summaryrefslogtreecommitdiff
path: root/unpack/restore_fstree.c
diff options
context:
space:
mode:
Diffstat (limited to 'unpack/restore_fstree.c')
-rw-r--r--unpack/restore_fstree.c171
1 files changed, 89 insertions, 82 deletions
diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c
index 5a20c5f..270b25a 100644
--- a/unpack/restore_fstree.c
+++ b/unpack/restore_fstree.c
@@ -1,103 +1,99 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
#include "rdsquashfs.h"
-static int restore_directory(int dirfd, tree_node_t *n, compressor_t *cmp,
- size_t block_size, frag_reader_t *frag,
- int sqfsfd, int flags)
+static int create_node(int dirfd, tree_node_t *n, compressor_t *cmp,
+ size_t block_size, frag_reader_t *frag,
+ int sqfsfd, int flags)
{
int fd;
- for (n = n->data.dir->children; n != NULL; n = n->next) {
- switch (n->mode & S_IFMT) {
- case S_IFDIR:
- if (mkdirat(dirfd, n->name, 0755) &&
- errno != EEXIST) {
- fprintf(stderr, "mkdir %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
+ switch (n->mode & S_IFMT) {
+ case S_IFDIR:
+ if (mkdirat(dirfd, n->name, 0755) && errno != EEXIST) {
+ fprintf(stderr, "mkdir %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
- fd = openat(dirfd, n->name, O_RDONLY | O_DIRECTORY);
- if (fd < 0) {
- fprintf(stderr, "open dir %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
+ fd = openat(dirfd, n->name, O_RDONLY | O_DIRECTORY);
+ if (fd < 0) {
+ fprintf(stderr, "open dir %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
- if (restore_directory(fd, n, cmp, block_size,
- frag, sqfsfd, flags)) {
+ for (n = n->data.dir->children; n != NULL; n = n->next) {
+ if (create_node(fd, n, cmp, block_size, frag, sqfsfd,
+ flags)) {
close(fd);
return -1;
}
+ }
- close(fd);
- break;
- case S_IFLNK:
- if (symlinkat(n->data.slink_target, dirfd, n->name)) {
- fprintf(stderr, "ln -s %s %s: %s\n",
- n->data.slink_target, n->name,
- strerror(errno));
- return -1;
- }
- break;
- case S_IFSOCK:
- case S_IFIFO:
- if (mknodat(dirfd, n->name,
- (n->mode & S_IFMT) | 0700, 0)) {
- fprintf(stderr, "creating %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
- break;
- case S_IFBLK:
- case S_IFCHR:
- if (mknodat(dirfd, n->name, (n->mode & S_IFMT),
- n->data.devno)) {
- fprintf(stderr, "creating device %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
- break;
- case S_IFREG:
- fd = openat(dirfd, n->name,
- O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0) {
- fprintf(stderr, "creating %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
-
- if (extract_file(n->data.file, cmp, block_size,
- frag, sqfsfd, fd)) {
- close(fd);
- return -1;
- }
+ close(fd);
+ break;
+ case S_IFLNK:
+ if (symlinkat(n->data.slink_target, dirfd, n->name)) {
+ fprintf(stderr, "ln -s %s %s: %s\n",
+ n->data.slink_target, n->name,
+ strerror(errno));
+ return -1;
+ }
+ break;
+ case S_IFSOCK:
+ case S_IFIFO:
+ if (mknodat(dirfd, n->name, (n->mode & S_IFMT) | 0700, 0)) {
+ fprintf(stderr, "creating %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (mknodat(dirfd, n->name, (n->mode & S_IFMT),
+ n->data.devno)) {
+ fprintf(stderr, "creating device %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
+ break;
+ case S_IFREG:
+ fd = openat(dirfd, n->name, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (fd < 0) {
+ fprintf(stderr, "creating %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
+ if (extract_file(n->data.file, cmp, block_size,
+ frag, sqfsfd, fd)) {
close(fd);
- break;
- default:
- break;
+ return -1;
}
- if (flags & UNPACK_CHOWN) {
- if (fchownat(dirfd, n->name, n->uid, n->gid,
- AT_SYMLINK_NOFOLLOW)) {
- fprintf(stderr, "chown %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
- }
+ close(fd);
+ break;
+ default:
+ break;
+ }
- if (flags & UNPACK_CHMOD) {
- if (fchmodat(dirfd, n->name, n->mode,
- AT_SYMLINK_NOFOLLOW)) {
- fprintf(stderr, "chmod %s: %s\n",
- n->name, strerror(errno));
- return -1;
- }
+ if (flags & UNPACK_CHOWN) {
+ if (fchownat(dirfd, n->name, n->uid, n->gid,
+ AT_SYMLINK_NOFOLLOW)) {
+ fprintf(stderr, "chown %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
}
}
+ if (flags & UNPACK_CHMOD) {
+ if (fchmodat(dirfd, n->name, n->mode,
+ AT_SYMLINK_NOFOLLOW)) {
+ fprintf(stderr, "chmod %s: %s\n",
+ n->name, strerror(errno));
+ return -1;
+ }
+ }
return 0;
}
@@ -105,6 +101,7 @@ int restore_fstree(const char *rootdir, tree_node_t *root, compressor_t *cmp,
size_t block_size, frag_reader_t *frag, int sqfsfd,
int flags)
{
+ tree_node_t *n;
int dirfd;
if (mkdir_p(rootdir))
@@ -116,8 +113,18 @@ int restore_fstree(const char *rootdir, tree_node_t *root, compressor_t *cmp,
return -1;
}
- if (restore_directory(dirfd, root, cmp, block_size, frag,
- sqfsfd, flags)) {
+ if (S_ISDIR(root->mode)) {
+ for (n = root->data.dir->children; n != NULL; n = n->next) {
+ if (create_node(dirfd, n, cmp, block_size, frag,
+ sqfsfd, flags)) {
+ close(dirfd);
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ if (create_node(dirfd, root, cmp, block_size, frag, sqfsfd, flags)) {
close(dirfd);
return -1;
}