From b637566020abe184cdda199d640c636a7565a05c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 6 Aug 2023 21:35:58 +0200 Subject: tar2sqfs: Add option to exclude files Using --exclude or -E it is now possible to exclude files from the input tar stream. The options can be used multiple times. Signed-off-by: Richard Weinberger --- bin/tar2sqfs/src/options.c | 66 +++++++++++++++++++++++++++++++++++++------- bin/tar2sqfs/src/tar2sqfs.c | 8 ++++-- bin/tar2sqfs/src/tar2sqfs.h | 2 ++ include/tar/tar.h | 7 ++++- lib/tar/src/iterator.c | 16 ++++++++++- lib/tar/test/tar_iterator.c | 4 +-- lib/tar/test/tar_iterator2.c | 2 +- lib/tar/test/tar_iterator3.c | 2 +- 8 files changed, 89 insertions(+), 18 deletions(-) diff --git a/bin/tar2sqfs/src/options.c b/bin/tar2sqfs/src/options.c index f2185a6..edc27ce 100644 --- a/bin/tar2sqfs/src/options.c +++ b/bin/tar2sqfs/src/options.c @@ -22,13 +22,14 @@ static struct option long_opts[] = { { "no-symlink-retarget", no_argument, NULL, 'S' }, { "no-tail-packing", no_argument, NULL, 'T' }, { "force", no_argument, NULL, 'f' }, + { "exclude-dir", required_argument, NULL, 'E' }, { "quiet", no_argument, NULL, 'q' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 }, }; -static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqSThV"; +static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqE:SThV"; static const char *usagestr = "Usage: tar2sqfs [OPTIONS...] \n" @@ -79,6 +80,7 @@ static const char *usagestr = " --exportable, -e Generate an export table for NFS support.\n" " --no-tail-packing, -T Do not perform tail end packing on files that\n" " are larger than block size.\n" +" --exclude-dir, -E Skip tar entry if glob matches.\n" " --force, -f Overwrite the output file if it exists.\n" " --quiet, -q Do not print out progress reports.\n" " --help, -h Print help text and exit.\n" @@ -91,6 +93,9 @@ bool no_tail_pack = false; bool no_symlink_retarget = false; sqfs_writer_cfg_t cfg; char *root_becomes = NULL; +char **excludedirs = NULL; +size_t num_excludedirs = 0; +static size_t max_excludedirs = 0; static void input_compressor_print_available(void) { @@ -114,8 +119,10 @@ static void input_compressor_print_available(void) void process_args(int argc, char **argv) { + size_t idx, new_count; bool have_compressor; int i, ret; + char **new; sqfs_writer_cfg_init(&cfg); @@ -134,18 +141,18 @@ void process_args(int argc, char **argv) case 'b': if (parse_size("Block size", &cfg.block_size, optarg, 0)) { - exit(EXIT_FAILURE); + goto fail; } break; case 'B': if (parse_size("Device block size", &cfg.devblksize, optarg, 0)) { - exit(EXIT_FAILURE); + goto fail; } if (cfg.devblksize < 1024) { fputs("Device block size must be at " "least 1024\n", stderr); - exit(EXIT_FAILURE); + goto fail; } break; case 'c': @@ -163,7 +170,7 @@ void process_args(int argc, char **argv) if (!have_compressor) { fprintf(stderr, "Unsupported compressor '%s'\n", optarg); - exit(EXIT_FAILURE); + goto fail; } cfg.comp_id = ret; @@ -191,7 +198,7 @@ void process_args(int argc, char **argv) root_becomes = strdup(optarg); if (root_becomes == NULL) { perror("copying root directory name"); - exit(EXIT_FAILURE); + goto fail; } if (canonicalize_name(root_becomes) != 0 || @@ -214,15 +221,39 @@ void process_args(int argc, char **argv) case 'q': cfg.quiet = true; break; + case 'E': + if (num_excludedirs == max_excludedirs) { + new_count = max_excludedirs ? max_excludedirs * 2 : 16; + new = realloc(excludedirs, + new_count * sizeof(excludedirs[0])); + if (new == NULL) + goto fail_errno; + + max_excludedirs = new_count; + excludedirs = new; + } + + excludedirs[num_excludedirs] = strdup(optarg); + if (excludedirs[num_excludedirs] == NULL) + goto fail_errno; + + if (canonicalize_name(excludedirs[num_excludedirs])) { + perror(optarg); + goto fail; + } + + ++num_excludedirs; + break; + case 'h': printf(usagestr, SQFS_DEFAULT_BLOCK_SIZE, SQFS_DEVBLK_SIZE); compressor_print_available(); input_compressor_print_available(); - exit(EXIT_SUCCESS); + goto out_success; case 'V': print_version("tar2sqfs"); - exit(EXIT_SUCCESS); + goto out_success; default: goto fail_arg; } @@ -251,7 +282,22 @@ void process_args(int argc, char **argv) goto fail_arg; } return; +fail_errno: + perror("parsing options"); + goto fail; fail_arg: - fputs("Try `tar2sqfs --help' for more information.\n", stderr); - exit(EXIT_FAILURE); + fputs("Try `tar2sqfsr --help' for more information.\n", stderr); + goto fail; +fail: + ret = EXIT_FAILURE; + goto out_exit; +out_success: + ret = EXIT_SUCCESS; + goto out_exit; +out_exit: + for (idx = 0; idx < num_excludedirs; ++idx) + free(excludedirs[idx]); + free(root_becomes); + free(excludedirs); + exit(ret); } diff --git a/bin/tar2sqfs/src/tar2sqfs.c b/bin/tar2sqfs/src/tar2sqfs.c index ed671f5..ae8b548 100644 --- a/bin/tar2sqfs/src/tar2sqfs.c +++ b/bin/tar2sqfs/src/tar2sqfs.c @@ -8,9 +8,10 @@ int main(int argc, char **argv) { - int status = EXIT_FAILURE; sqfs_istream_t *input_file = NULL; + tar_iterator_opts topts = { 0 }; dir_iterator_t *tar = NULL; + int status = EXIT_FAILURE; sqfs_writer_t sqfs; int ret; @@ -22,7 +23,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - tar = tar_open_stream(input_file); + topts.excludedirs = excludedirs; + topts.num_excludedirs = num_excludedirs; + + tar = tar_open_stream(input_file, &topts); sqfs_drop(input_file); if (tar == NULL) { fputs("Creating tar stream: out-of-memory\n", stderr); diff --git a/bin/tar2sqfs/src/tar2sqfs.h b/bin/tar2sqfs/src/tar2sqfs.h index e853ae9..5dcfad7 100644 --- a/bin/tar2sqfs/src/tar2sqfs.h +++ b/bin/tar2sqfs/src/tar2sqfs.h @@ -29,6 +29,8 @@ extern bool no_tail_pack; extern bool no_symlink_retarget; extern sqfs_writer_cfg_t cfg; extern char *root_becomes; +extern char **excludedirs; +extern size_t num_excludedirs; void process_args(int argc, char **argv); diff --git a/include/tar/tar.h b/include/tar/tar.h index 52a0562..811ac47 100644 --- a/include/tar/tar.h +++ b/include/tar/tar.h @@ -39,6 +39,11 @@ typedef struct { sqfs_s64 mtime; } tar_header_decoded_t; +typedef struct { + char **excludedirs; + size_t num_excludedirs; +} tar_iterator_opts; + #ifdef __cplusplus extern "C" { #endif @@ -63,7 +68,7 @@ int read_header(sqfs_istream_t *fp, tar_header_decoded_t *out); void clear_header(tar_header_decoded_t *hdr); -dir_iterator_t *tar_open_stream(sqfs_istream_t *stream); +dir_iterator_t *tar_open_stream(sqfs_istream_t *stream, tar_iterator_opts *opts); /* Write zero bytes to an output file to padd it to the tar record size. diff --git a/lib/tar/src/iterator.c b/lib/tar/src/iterator.c index 6b456d6..a2708a0 100644 --- a/lib/tar/src/iterator.c +++ b/lib/tar/src/iterator.c @@ -16,11 +16,14 @@ #include #include #include +#include typedef struct { dir_iterator_t base; tar_header_decoded_t current; sqfs_istream_t *stream; + char **excludedirs; + size_t num_excludedirs; int state; /* File I/O wrapper related */ @@ -167,6 +170,7 @@ static void strm_destroy(sqfs_object_t *obj) static int it_next(dir_iterator_t *it, sqfs_dir_entry_t **out) { tar_iterator_t *tar = (tar_iterator_t *)it; + size_t idx; int ret; *out = NULL; @@ -209,6 +213,11 @@ retry: return tar->state; } + for (idx = 0; idx < tar->num_excludedirs; idx++) { + if (fnmatch(tar->excludedirs[idx], tar->current.name, 0) == 0) + goto retry; + } + *out = sqfs_dir_entry_create(tar->current.name, tar->current.mode, 0); if ((*out) == NULL) { tar->state = SQFS_ERROR_ALLOC; @@ -350,7 +359,7 @@ static int tar_probe(const sqfs_u8 *data, size_t size) return 0; } -dir_iterator_t *tar_open_stream(sqfs_istream_t *strm) +dir_iterator_t *tar_open_stream(sqfs_istream_t *strm, tar_iterator_opts *opts) { tar_iterator_t *tar = calloc(1, sizeof(*tar)); dir_iterator_t *it = (dir_iterator_t *)tar; @@ -370,6 +379,11 @@ dir_iterator_t *tar_open_stream(sqfs_istream_t *strm) it->open_file_ro = it_open_file_ro; it->read_xattr = it_read_xattr; + if (opts) { + tar->excludedirs = opts->excludedirs; + tar->num_excludedirs = opts->num_excludedirs; + } + /* proble if the stream is compressed */ ret = strm->get_buffered_data(strm, &ptr, &size, sizeof(tar_header_t)); diff --git a/lib/tar/test/tar_iterator.c b/lib/tar/test/tar_iterator.c index 6931a7c..cd24c94 100644 --- a/lib/tar/test/tar_iterator.c +++ b/lib/tar/test/tar_iterator.c @@ -46,7 +46,7 @@ int main(int argc, char **argv) TEST_EQUAL_I(iret, 0); TEST_NOT_NULL(fp); TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - it = tar_open_stream(fp); + it = tar_open_stream(fp, NULL); TEST_NOT_NULL(it); TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); @@ -115,7 +115,7 @@ int main(int argc, char **argv) 0); TEST_EQUAL_I(iret, 0); TEST_NOT_NULL(fp); - it = tar_open_stream(fp); + it = tar_open_stream(fp, NULL); TEST_NOT_NULL(it); /* read entry */ diff --git a/lib/tar/test/tar_iterator2.c b/lib/tar/test/tar_iterator2.c index 681835d..7b22af3 100644 --- a/lib/tar/test/tar_iterator2.c +++ b/lib/tar/test/tar_iterator2.c @@ -57,7 +57,7 @@ int main(int argc, char **argv) 0); TEST_EQUAL_I(iret, 0); TEST_NOT_NULL(fp); - it = tar_open_stream(fp); + it = tar_open_stream(fp, NULL); TEST_NOT_NULL(it); sqfs_drop(fp); diff --git a/lib/tar/test/tar_iterator3.c b/lib/tar/test/tar_iterator3.c index f8d0bda..7973441 100644 --- a/lib/tar/test/tar_iterator3.c +++ b/lib/tar/test/tar_iterator3.c @@ -28,7 +28,7 @@ int main(int argc, char **argv) TEST_EQUAL_I(ret, 0); TEST_NOT_NULL(fp); TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - it = tar_open_stream(fp); + it = tar_open_stream(fp, NULL); TEST_NOT_NULL(it); TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); -- cgit v1.2.3