aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2023-08-06 21:35:58 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2023-08-10 09:25:51 +0200
commitb637566020abe184cdda199d640c636a7565a05c (patch)
treec9e3057cff9eaf9fa7d33016096c6228348f6f45
parente7ecb1f92ae618a56ee8eabb6cbf98365de3695a (diff)
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 <richard@nod.at>
-rw-r--r--bin/tar2sqfs/src/options.c66
-rw-r--r--bin/tar2sqfs/src/tar2sqfs.c8
-rw-r--r--bin/tar2sqfs/src/tar2sqfs.h2
-rw-r--r--include/tar/tar.h7
-rw-r--r--lib/tar/src/iterator.c16
-rw-r--r--lib/tar/test/tar_iterator.c4
-rw-r--r--lib/tar/test/tar_iterator2.c2
-rw-r--r--lib/tar/test/tar_iterator3.c2
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...] <sqfsfile>\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 <glob> 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 <string.h>
#include <assert.h>
#include <stdbool.h>
+#include <fnmatch.h>
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);