diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-01 16:17:38 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-01 16:23:07 +0200 |
commit | 78e35e9d44b2ec7a36a0acac1ab63343b56b9c2c (patch) | |
tree | 79125d4f92e5d2fab68d958cf76cfde8fc642c2e | |
parent | cccbd5aa139b8e0cac233f317cb3e7252daae0d9 (diff) |
Add ability to sqfs2tar to optionally copy over xattrs
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | tar/sqfs2tar.c | 60 |
1 files changed, 55 insertions, 5 deletions
diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c index 07be2b4..3a7d92d 100644 --- a/tar/sqfs2tar.c +++ b/tar/sqfs2tar.c @@ -27,11 +27,12 @@ static struct option long_opts[] = { { "subdir", required_argument, NULL, 'd' }, { "keep-as-dir", no_argument, NULL, 'k' }, { "no-skip", no_argument, NULL, 's' }, + { "no-xattr", no_argument, NULL, 'X' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, }; -static const char *short_opts = "d:kshV"; +static const char *short_opts = "d:ksXhV"; static const char *usagestr = "Usage: sqfs2tar [OPTIONS...] <sqfsfile>\n" @@ -52,8 +53,9 @@ static const char *usagestr = " prefix for all unpacked files.\n" " Using --subdir more than once implies\n" " --keep-as-dir.\n" +" --no-xattr, -X Do not copy extended attributes.\n" "\n" -" --no-skip Abort if a file cannot be stored in a tar\n" +" --no-skip, -s Abort if a file cannot be stored in a tar\n" " archive. By default, it is simply skipped\n" " and a warning is written to stderr.\n" "\n" @@ -71,6 +73,7 @@ static const char *filename; static unsigned int record_counter; static bool dont_skip = false; static bool keep_as_dir = false; +static bool no_xattr = false; static const char *current_subdir = NULL; @@ -119,6 +122,9 @@ static void process_args(int argc, char **argv) case 's': dont_skip = true; break; + case 'X': + no_xattr = true; + break; case 'h': fputs(usagestr, stdout); goto out_success; @@ -175,8 +181,40 @@ static int terminate_archive(void) buffer, sizeof(buffer)); } +static tar_xattr_t *gen_xattr_list(fstree_t *fs, tree_xattr_t *xattr) +{ + const char *key, *value; + tar_xattr_t *list; + size_t i; + + list = malloc(sizeof(list[0]) * xattr->num_attr); + if (list == NULL) { + perror("creating xattr list"); + return NULL; + } + + for (i = 0; i < xattr->num_attr; ++i) { + key = str_table_get_string(&fs->xattr_keys, + xattr->attr[i].key_index); + value = str_table_get_string(&fs->xattr_values, + xattr->attr[i].value_index); + + list[i].key = (char *)key; + list[i].value = (char *)value; + + if (i + 1 < xattr->num_attr) { + list[i].next = list + i + 1; + } else { + list[i].next = NULL; + } + } + + return list; +} + static int write_tree_dfs(fstree_t *fs, tree_node_t *n, data_reader_t *data) { + tar_xattr_t *xattr = NULL; size_t len, name_len; char *name, *target; struct stat sb; @@ -210,9 +248,18 @@ static int write_tree_dfs(fstree_t *fs, tree_node_t *n, data_reader_t *data) fstree_node_stat(fs, n, &sb); + if (!no_xattr && n->xattr != NULL) { + xattr = gen_xattr_list(fs, n->xattr); + if (xattr == NULL) { + free(name); + return -1; + } + } + target = S_ISLNK(sb.st_mode) ? n->data.slink_target : NULL; - ret = write_tar_header(STDOUT_FILENO, &sb, name, target, NULL, + ret = write_tar_header(STDOUT_FILENO, &sb, name, target, xattr, record_counter++); + free(xattr); if (ret > 0) { if (dont_skip) { @@ -254,13 +301,13 @@ skip_hdr: int main(int argc, char **argv) { + int sqfsfd, rdtree_flags = 0; data_reader_t *data = NULL; int status = EXIT_FAILURE; sqfs_super_t super; compressor_t *cmp; tree_node_t *root; fstree_t fs; - int sqfsfd; size_t i; process_args(argc, argv); @@ -290,7 +337,10 @@ int main(int argc, char **argv) goto out_cmp; } - if (deserialize_fstree(&fs, &super, cmp, sqfsfd, 0)) + if (!no_xattr) + rdtree_flags |= RDTREE_READ_XATTR; + + if (deserialize_fstree(&fs, &super, cmp, sqfsfd, rdtree_flags)) goto out_cmp; data = data_reader_create(sqfsfd, &super, cmp); |