From 84210b0ba9f2d2208981fb71967bdcf6001f44b2 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 16 Nov 2019 13:44:17 +0100 Subject: Remove pushd/popd usage from rdsquashfs unpacking code Instead, reconstruct the full path and use that instead. We do that anyway if --quiet is not set. Signed-off-by: David Oberhollenzer --- unpack/rdsquashfs.c | 11 +++-- unpack/restore_fstree.c | 116 ++++++++++++++++++++++++++---------------------- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index 2f84264..4acc71e 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -135,10 +135,12 @@ int main(int argc, char **argv) case OP_UNPACK: if (opt.unpack_root != NULL) { if (mkdir_p(opt.unpack_root)) - return -1; + goto out; - if (pushd(opt.unpack_root)) - return -1; + if (chdir(opt.unpack_root)) { + perror(opt.unpack_root); + goto out; + } } if (restore_fstree(n, opt.flags)) @@ -149,9 +151,6 @@ int main(int argc, char **argv) if (update_tree_attribs(xattr, n, opt.flags)) goto out; - - if (opt.unpack_root != NULL && popd() != 0) - goto out; break; case OP_DESCRIBE: if (describe_tree(n, opt.unpack_root)) diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c index 6995d47..dac1a8c 100644 --- a/unpack/restore_fstree.c +++ b/unpack/restore_fstree.c @@ -18,50 +18,49 @@ static int create_node(const sqfs_tree_node_t *n, int flags) return 0; } - if (!(flags & UNPACK_QUIET)) { - name = sqfs_tree_node_get_path(n); - if (name != NULL) { - ret = canonicalize_name(name); - assert(ret == 0); - printf("creating %s\n", name); - free(name); - } + name = sqfs_tree_node_get_path(n); + if (name == NULL) { + fprintf(stderr, "Constructing full path for '%s': %s\n", + (const char *)n->name, strerror(errno)); + return -1; } + ret = canonicalize_name(name); + assert(ret == 0); + + if (!(flags & UNPACK_QUIET)) + printf("creating %s\n", name); + switch (n->inode->base.mode & S_IFMT) { case S_IFDIR: - if (mkdir((const char *)n->name, 0755) && errno != EEXIST) { + if (mkdir(name, 0755) && errno != EEXIST) { fprintf(stderr, "mkdir %s: %s\n", - n->name, strerror(errno)); - return -1; + name, strerror(errno)); + goto fail; } - if (pushd((const char *)n->name)) - return -1; + free(name); + name = NULL; for (c = n->children; c != NULL; c = c->next) { if (create_node(c, flags)) - return -1; + goto fail; } - - if (popd()) - return -1; break; case S_IFLNK: - if (symlink(n->inode->slink_target, (const char *)n->name)) { + if (symlink(n->inode->slink_target, name)) { fprintf(stderr, "ln -s %s %s: %s\n", - n->inode->slink_target, n->name, + n->inode->slink_target, name, strerror(errno)); - return -1; + goto fail; } break; case S_IFSOCK: case S_IFIFO: - if (mknod((const char *)n->name, - (n->inode->base.mode & S_IFMT) | 0700, 0)) { + if (mknod(name, (n->inode->base.mode & S_IFMT) | 0700, 0)) { fprintf(stderr, "creating %s: %s\n", - n->name, strerror(errno)); - return -1; + name, strerror(errno)); + goto fail; } break; case S_IFBLK: @@ -75,21 +74,19 @@ static int create_node(const sqfs_tree_node_t *n, int flags) devno = n->inode->data.dev.devno; } - if (mknod((const char *)n->name, n->inode->base.mode & S_IFMT, - devno)) { + if (mknod(name, n->inode->base.mode & S_IFMT, devno)) { fprintf(stderr, "creating device %s: %s\n", - n->name, strerror(errno)); - return -1; + name, strerror(errno)); + goto fail; } break; } case S_IFREG: - fd = open((const char *)n->name, O_WRONLY | O_CREAT | O_EXCL, - 0600); + fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) { fprintf(stderr, "creating %s: %s\n", - n->name, strerror(errno)); - return -1; + name, strerror(errno)); + goto fail; } close(fd); @@ -98,11 +95,16 @@ static int create_node(const sqfs_tree_node_t *n, int flags) break; } + free(name); return 0; +fail: + free(name); + return -1; } #ifdef HAVE_SYS_XATTR_H -static int set_xattr(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *n) +static int set_xattr(const char *path, sqfs_xattr_reader_t *xattr, + const sqfs_tree_node_t *n) { sqfs_xattr_value_t *value; sqfs_xattr_entry_t *key; @@ -138,11 +140,11 @@ static int set_xattr(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *n) return -1; } - ret = lsetxattr((const char *)n->name, (const char *)key->key, + ret = lsetxattr(path, (const char *)key->key, value->value, value->size, 0); if (ret) { fprintf(stderr, "setting xattr '%s' on %s: %s\n", - key->key, n->name, strerror(errno)); + key->key, path, strerror(errno)); } free(key); @@ -159,27 +161,33 @@ static int set_attribs(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *n, int flags) { const sqfs_tree_node_t *c; + char *path; + int ret; if (!is_filename_sane((const char *)n->name)) return 0; if (S_ISDIR(n->inode->base.mode)) { - if (pushd((const char *)n->name)) - return -1; - for (c = n->children; c != NULL; c = c->next) { if (set_attribs(xattr, c, flags)) return -1; } + } - if (popd()) - return -1; + path = sqfs_tree_node_get_path(n); + if (path == NULL) { + fprintf(stderr, "Reconstructing full path: %s\n", + strerror(errno)); + return -1; } + ret = canonicalize_name(path); + assert(ret == 0); + #ifdef HAVE_SYS_XATTR_H if ((flags & UNPACK_SET_XATTR) && xattr != NULL) { - if (set_xattr(xattr, n)) - return -1; + if (set_xattr(path, xattr, n)) + goto fail; } #endif @@ -190,32 +198,36 @@ static int set_attribs(sqfs_xattr_reader_t *xattr, times[0].tv_sec = n->inode->base.mod_time; times[1].tv_sec = n->inode->base.mod_time; - if (utimensat(AT_FDCWD, (const char *)n->name, times, - AT_SYMLINK_NOFOLLOW)) { + if (utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW)) { fprintf(stderr, "setting timestamp on %s: %s\n", - n->name, strerror(errno)); - return -1; + path, strerror(errno)); + goto fail; } } if (flags & UNPACK_CHOWN) { - if (fchownat(AT_FDCWD, (const char *)n->name, n->uid, n->gid, + if (fchownat(AT_FDCWD, path, n->uid, n->gid, AT_SYMLINK_NOFOLLOW)) { fprintf(stderr, "chown %s: %s\n", - n->name, strerror(errno)); - return -1; + path, strerror(errno)); + goto fail; } } if (flags & UNPACK_CHMOD && !S_ISLNK(n->inode->base.mode)) { - if (fchmodat(AT_FDCWD, (const char *)n->name, + if (fchmodat(AT_FDCWD, path, n->inode->base.mode & ~S_IFMT, 0)) { fprintf(stderr, "chmod %s: %s\n", - n->name, strerror(errno)); - return -1; + path, strerror(errno)); + goto fail; } } + + free(path); return 0; +fail: + free(path); + return -1; } int restore_fstree(sqfs_tree_node_t *root, int flags) -- cgit v1.2.3