diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-04 01:10:24 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-04 01:15:11 +0200 |
commit | 85e2e1629ba43ea2b2a11b1f81e3538e3cea64da (patch) | |
tree | 4d6da28635d2543040a9481e2853765f993f9648 | |
parent | d443bc79b599eb6e6054a0feb4d0d0654b2c683f (diff) |
Make sure file listing generated by rdsquashfs -d is propperly escaped
File names may contain traces of white space.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | unpack/describe.c | 97 | ||||
-rw-r--r-- | unpack/rdsquashfs.c | 3 | ||||
-rw-r--r-- | unpack/rdsquashfs.h | 2 |
3 files changed, 70 insertions, 32 deletions
diff --git a/unpack/describe.c b/unpack/describe.c index 627bc2b..c3166c4 100644 --- a/unpack/describe.c +++ b/unpack/describe.c @@ -6,14 +6,46 @@ */ #include "rdsquashfs.h" -static void print_name(tree_node_t *n) +static int print_name(tree_node_t *n) { - if (n->parent != NULL) { - print_name(n->parent); - fputc('/', stdout); + char *start, *ptr, *name = fstree_get_path(n); + int ret; + + if (name == NULL) { + perror("Recovering file path of tree node"); + return -1; + } + + ret = canonicalize_name(name); + assert(ret == 0); + + if (strchr(name, ' ') == NULL && strchr(name, '"') == NULL) { + fputs(name, stdout); + } else { + fputc('"', stdout); + + ptr = strchr(name, '"'); + + if (ptr != NULL) { + start = name; + + do { + fwrite(start, 1, ptr - start, stdout); + fputs("\\\"", stdout); + start = ptr + 1; + ptr = strchr(start, '"'); + } while (ptr != NULL); + + fputs(start, stdout); + } else { + fputs(name, stdout); + } + + fputc('"', stdout); } - fputs(n->name, stdout); + free(name); + return 0; } static void print_perm(tree_node_t *n) @@ -21,56 +53,61 @@ static void print_perm(tree_node_t *n) printf(" 0%o %d %d", n->mode & (~S_IFMT), n->uid, n->gid); } -static void print_simple(const char *type, tree_node_t *n, const char *extra) +static int print_simple(const char *type, tree_node_t *n, const char *extra) { printf("%s ", type); - print_name(n); + if (print_name(n)) + return -1; print_perm(n); if (extra != NULL) printf(" %s", extra); fputc('\n', stdout); + return 0; } -void describe_tree(tree_node_t *root, const char *unpack_root) +int describe_tree(tree_node_t *root, const char *unpack_root) { tree_node_t *n; switch (root->mode & S_IFMT) { case S_IFSOCK: - print_simple("sock", root, NULL); - break; + return print_simple("sock", root, NULL); case S_IFLNK: - print_simple("slink", root, root->data.slink_target); - break; + return print_simple("slink", root, root->data.slink_target); case S_IFIFO: - print_simple("pipe", root, NULL); - break; + return print_simple("pipe", root, NULL); case S_IFREG: - if (unpack_root != NULL) { - fputs("file ", stdout); - print_name(root); - print_perm(root); - printf(" %s", unpack_root); - print_name(root); - fputc('\n', stdout); - } else { - print_simple("file", root, NULL); - } + if (unpack_root == NULL) + return print_simple("file", root, NULL); + + fputs("file ", stdout); + if (print_name(root)) + return -1; + print_perm(root); + printf(" %s/", unpack_root); + if (print_name(root)) + return -1; + fputc('\n', stdout); break; case S_IFCHR: case S_IFBLK: { char buffer[32]; sprintf(buffer, "%c %d %d", S_ISCHR(root->mode) ? 'c' : 'b', major(root->data.devno), minor(root->data.devno)); - print_simple("nod", root, buffer); - break; + return print_simple("nod", root, buffer); } case S_IFDIR: - if (root->name[0] != '\0') - print_simple("dir", root, NULL); + if (root->name[0] != '\0') { + if (print_simple("dir", root, NULL)) + return -1; + } - for (n = root->data.dir->children; n != NULL; n = n->next) - describe_tree(n, unpack_root); + for (n = root->data.dir->children; n != NULL; n = n->next) { + if (describe_tree(n, unpack_root)) + return -1; + } break; } + + return 0; } diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index 2162cc4..dc43fcd 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -119,7 +119,8 @@ int main(int argc, char **argv) goto out_fs; break; case OP_DESCRIBE: - describe_tree(fs.root, opt.unpack_root); + if (describe_tree(fs.root, opt.unpack_root)) + goto out_fs; break; case OP_RDATTR: if (n->xattr != NULL) diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h index 44635d8..ca4825b 100644 --- a/unpack/rdsquashfs.h +++ b/unpack/rdsquashfs.h @@ -71,7 +71,7 @@ int update_tree_attribs(fstree_t *fs, tree_node_t *root, int flags); int fill_unpacked_files(fstree_t *fs, data_reader_t *data, int flags, unsigned int num_jobs); -void describe_tree(tree_node_t *root, const char *unpack_root); +int describe_tree(tree_node_t *root, const char *unpack_root); void process_command_line(options_t *opt, int argc, char **argv); |