diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-05-27 14:52:08 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-05-30 17:49:40 +0200 |
commit | 4332c116b303e0f86aaac4ae0bf699db5744769d (patch) | |
tree | 045d3ec030ec16862c114ed31994c6cfd6bf9bb9 /bin | |
parent | 8aa0366b85ce621ec54637ab4f9d37ad1e636e8f (diff) |
Cleanup: try to split tar2sqfs.c in a reasonable way
This commit breaks tar2sqfs.c into multiple files:
- options.c contains the command line argument processing
- process_tarball.c contains the main tar repacking code
- tar2sqfs.c contains what is left (the main function)
- A header is added for gluing it all together.
No actual code is changed. The tar repacking code is slightly modified
to pass the sqfs writer and input file pointer around as argument rather
than using a global variable.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'bin')
-rw-r--r-- | bin/Makemodule.am | 3 | ||||
-rw-r--r-- | bin/tar2sqfs/options.c (renamed from bin/tar2sqfs.c) | 330 | ||||
-rw-r--r-- | bin/tar2sqfs/process_tarball.c | 272 | ||||
-rw-r--r-- | bin/tar2sqfs/tar2sqfs.c | 46 | ||||
-rw-r--r-- | bin/tar2sqfs/tar2sqfs.h | 37 |
5 files changed, 364 insertions, 324 deletions
diff --git a/bin/Makemodule.am b/bin/Makemodule.am index 3e32308..2328d5c 100644 --- a/bin/Makemodule.am +++ b/bin/Makemodule.am @@ -4,7 +4,8 @@ sqfs2tar_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) sqfs2tar_LDADD = libcommon.a libutil.a libsquashfs.la libtar.a libcompat.a sqfs2tar_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) -tar2sqfs_SOURCES = bin/tar2sqfs.c +tar2sqfs_SOURCES = bin/tar2sqfs/tar2sqfs.c bin/tar2sqfs/tar2sqfs.h +tar2sqfs_SOURCES += bin/tar2sqfs/options.c bin/tar2sqfs/process_tarball.c tar2sqfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) tar2sqfs_LDADD = libcommon.a libsquashfs.la libtar.a tar2sqfs_LDADD += libfstree.a libcompat.a libfstree.a $(LZO_LIBS) diff --git a/bin/tar2sqfs.c b/bin/tar2sqfs/options.c index bdd36e1..b5aa3ba 100644 --- a/bin/tar2sqfs.c +++ b/bin/tar2sqfs/options.c @@ -1,23 +1,4 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * tar2sqfs.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" -#include "common.h" -#include "compat.h" -#include "tar.h" - -#include <stdlib.h> -#include <getopt.h> -#include <string.h> -#include <stdio.h> -#include <fcntl.h> - -#ifdef _WIN32 -#include <io.h> -#endif +#include "tar2sqfs.h" static struct option long_opts[] = { { "root-becomes", required_argument, NULL, 'r' }, @@ -100,15 +81,13 @@ static const char *usagestr = "\txzcat rootfs.tar.xz | tar2sqfs rootfs.sqfs\n" "\n"; -static bool dont_skip = false; -static bool keep_time = true; -static bool no_tail_pack = false; -static sqfs_writer_cfg_t cfg; -static sqfs_writer_t sqfs; -static FILE *input_file = NULL; -static char *root_becomes = NULL; +bool dont_skip = false; +bool keep_time = true; +bool no_tail_pack = false; +sqfs_writer_cfg_t cfg; +char *root_becomes = NULL; -static void process_args(int argc, char **argv) +void process_args(int argc, char **argv) { bool have_compressor; int i, ret; @@ -247,298 +226,3 @@ fail_arg: fputs("Try `tar2sqfs --help' for more information.\n", stderr); exit(EXIT_FAILURE); } - -static int write_file(tar_header_decoded_t *hdr, file_info_t *fi, - sqfs_u64 filesize) -{ - sqfs_file_t *file; - int flags; - int ret; - - file = sqfs_get_stdin_file(input_file, hdr->sparse, filesize); - if (file == NULL) { - perror("packing files"); - return -1; - } - - flags = 0; - if (no_tail_pack && filesize > cfg.block_size) - flags |= SQFS_BLK_DONT_FRAGMENT; - - ret = write_data_from_file(hdr->name, sqfs.data, - (sqfs_inode_generic_t **)&fi->user_ptr, - file, flags); - sqfs_destroy(file); - - if (ret) - return -1; - - return skip_padding(input_file, hdr->sparse == NULL ? - filesize : hdr->record_size); -} - -static int copy_xattr(tree_node_t *node, const tar_header_decoded_t *hdr) -{ - tar_xattr_t *xattr; - int ret; - - ret = sqfs_xattr_writer_begin(sqfs.xwr); - if (ret) { - sqfs_perror(hdr->name, "beginning xattr block", ret); - return -1; - } - - for (xattr = hdr->xattr; xattr != NULL; xattr = xattr->next) { - if (sqfs_get_xattr_prefix_id(xattr->key) < 0) { - fprintf(stderr, "%s: squashfs does not " - "support xattr prefix of %s\n", - dont_skip ? "ERROR" : "WARNING", - xattr->key); - - if (dont_skip) - return -1; - continue; - } - - ret = sqfs_xattr_writer_add(sqfs.xwr, xattr->key, xattr->value, - xattr->value_len); - if (ret) { - sqfs_perror(hdr->name, "storing xattr key-value pair", - ret); - return -1; - } - } - - ret = sqfs_xattr_writer_end(sqfs.xwr, &node->xattr_idx); - if (ret) { - sqfs_perror(hdr->name, "completing xattr block", ret); - return -1; - } - - return 0; -} - -static int create_node_and_repack_data(tar_header_decoded_t *hdr) -{ - tree_node_t *node; - - if (hdr->is_hard_link) { - node = fstree_add_hard_link(&sqfs.fs, hdr->name, - hdr->link_target); - if (node == NULL) - goto fail_errno; - - if (!cfg.quiet) { - printf("Hard link %s -> %s\n", hdr->name, - hdr->link_target); - } - return 0; - } - - if (!keep_time) { - hdr->sb.st_mtime = sqfs.fs.defaults.st_mtime; - } - - node = fstree_add_generic(&sqfs.fs, hdr->name, - &hdr->sb, hdr->link_target); - if (node == NULL) - goto fail_errno; - - if (!cfg.quiet) - printf("Packing %s\n", hdr->name); - - if (!cfg.no_xattr) { - if (copy_xattr(node, hdr)) - return -1; - } - - if (S_ISREG(hdr->sb.st_mode)) { - if (write_file(hdr, &node->data.file, hdr->sb.st_size)) - return -1; - } - - return 0; -fail_errno: - perror(hdr->name); - return -1; -} - -static int set_root_attribs(const tar_header_decoded_t *hdr) -{ - if (hdr->is_hard_link || !S_ISDIR(hdr->sb.st_mode)) { - fprintf(stderr, "'%s' is not a directory!\n", hdr->name); - return -1; - } - - sqfs.fs.root->uid = hdr->sb.st_uid; - sqfs.fs.root->gid = hdr->sb.st_gid; - sqfs.fs.root->mode = hdr->sb.st_mode; - - if (keep_time) - sqfs.fs.root->mod_time = hdr->sb.st_mtime; - - if (!cfg.no_xattr) { - if (copy_xattr(sqfs.fs.root, hdr)) - return -1; - } - - return 0; -} - -static int process_tar_ball(void) -{ - bool skip, is_root, is_prefixed; - tar_header_decoded_t hdr; - sqfs_u64 offset, count; - sparse_map_t *m; - size_t rootlen; - int ret; - - rootlen = root_becomes == NULL ? 0 : strlen(root_becomes); - - for (;;) { - ret = read_header(input_file, &hdr); - if (ret > 0) - break; - if (ret < 0) - return -1; - - if (hdr.mtime < 0) - hdr.mtime = 0; - - if ((sqfs_u64)hdr.mtime > 0x0FFFFFFFFUL) - hdr.mtime = 0x0FFFFFFFFUL; - - hdr.sb.st_mtime = hdr.mtime; - - skip = false; - is_root = false; - is_prefixed = true; - - if (hdr.name == NULL || canonicalize_name(hdr.name) != 0) { - fprintf(stderr, "skipping '%s' (invalid name)\n", - hdr.name); - skip = true; - } - - if (root_becomes != NULL) { - if (strncmp(hdr.name, root_becomes, rootlen) == 0) { - if (hdr.name[rootlen] == '\0') { - is_root = true; - } else if (hdr.name[rootlen] != '/') { - is_prefixed = false; - } - } else { - is_prefixed = false; - } - - if (is_prefixed && !is_root) { - memmove(hdr.name, hdr.name + rootlen + 1, - strlen(hdr.name + rootlen + 1) + 1); - } - - if (is_prefixed && hdr.name[0] == '\0') { - fputs("skipping entry with empty name\n", - stderr); - skip = true; - } - } else if (hdr.name[0] == '\0') { - is_root = true; - } - - if (!is_prefixed) { - clear_header(&hdr); - continue; - } - - if (is_root) { - if (set_root_attribs(&hdr)) - goto fail; - clear_header(&hdr); - continue; - } - - if (!skip && hdr.unknown_record) { - fprintf(stderr, "%s: unknown entry type\n", hdr.name); - skip = true; - } - - if (!skip && hdr.sparse != NULL) { - offset = hdr.sparse->offset; - count = 0; - - for (m = hdr.sparse; m != NULL; m = m->next) { - if (m->offset < offset) { - skip = true; - break; - } - offset = m->offset + m->count; - count += m->count; - } - - if (count != hdr.record_size) - skip = true; - - if (skip) { - fprintf(stderr, "%s: broken sparse " - "file layout\n", hdr.name); - } - } - - if (skip) { - if (dont_skip) - goto fail; - if (skip_entry(input_file, hdr.sb.st_size)) - goto fail; - - clear_header(&hdr); - continue; - } - - if (create_node_and_repack_data(&hdr)) - goto fail; - - clear_header(&hdr); - } - - return 0; -fail: - clear_header(&hdr); - return -1; -} - -int main(int argc, char **argv) -{ - int status = EXIT_FAILURE; - - process_args(argc, argv); - -#ifdef _WIN32 - _setmode(_fileno(stdin), _O_BINARY); - input_file = stdin; -#else - input_file = freopen(NULL, "rb", stdin); -#endif - - if (input_file == NULL) { - perror("changing stdin to binary mode"); - return EXIT_FAILURE; - } - - if (sqfs_writer_init(&sqfs, &cfg)) - return EXIT_FAILURE; - - if (process_tar_ball()) - goto out; - - if (fstree_post_process(&sqfs.fs)) - goto out; - - if (sqfs_writer_finish(&sqfs, &cfg)) - goto out; - - status = EXIT_SUCCESS; -out: - sqfs_writer_cleanup(&sqfs, status); - return status; -} diff --git a/bin/tar2sqfs/process_tarball.c b/bin/tar2sqfs/process_tarball.c new file mode 100644 index 0000000..3863014 --- /dev/null +++ b/bin/tar2sqfs/process_tarball.c @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * process_tarball.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "tar2sqfs.h" + +static int write_file(FILE *input_file, sqfs_writer_t *sqfs, + const tar_header_decoded_t *hdr, + file_info_t *fi, sqfs_u64 filesize) +{ + sqfs_file_t *file; + int flags; + int ret; + + file = sqfs_get_stdin_file(input_file, hdr->sparse, filesize); + if (file == NULL) { + perror("packing files"); + return -1; + } + + flags = 0; + if (no_tail_pack && filesize > cfg.block_size) + flags |= SQFS_BLK_DONT_FRAGMENT; + + ret = write_data_from_file(hdr->name, sqfs->data, + (sqfs_inode_generic_t **)&fi->user_ptr, + file, flags); + sqfs_destroy(file); + + if (ret) + return -1; + + return skip_padding(input_file, hdr->sparse == NULL ? + filesize : hdr->record_size); +} + +static int copy_xattr(sqfs_writer_t *sqfs, tree_node_t *node, + const tar_header_decoded_t *hdr) +{ + tar_xattr_t *xattr; + int ret; + + ret = sqfs_xattr_writer_begin(sqfs->xwr); + if (ret) { + sqfs_perror(hdr->name, "beginning xattr block", ret); + return -1; + } + + for (xattr = hdr->xattr; xattr != NULL; xattr = xattr->next) { + if (sqfs_get_xattr_prefix_id(xattr->key) < 0) { + fprintf(stderr, "%s: squashfs does not " + "support xattr prefix of %s\n", + dont_skip ? "ERROR" : "WARNING", + xattr->key); + + if (dont_skip) + return -1; + continue; + } + + ret = sqfs_xattr_writer_add(sqfs->xwr, xattr->key, xattr->value, + xattr->value_len); + if (ret) { + sqfs_perror(hdr->name, "storing xattr key-value pair", + ret); + return -1; + } + } + + ret = sqfs_xattr_writer_end(sqfs->xwr, &node->xattr_idx); + if (ret) { + sqfs_perror(hdr->name, "completing xattr block", ret); + return -1; + } + + return 0; +} + +static int create_node_and_repack_data(FILE *input_file, sqfs_writer_t *sqfs, + tar_header_decoded_t *hdr) +{ + tree_node_t *node; + + if (hdr->is_hard_link) { + node = fstree_add_hard_link(&sqfs->fs, hdr->name, + hdr->link_target); + if (node == NULL) + goto fail_errno; + + if (!cfg.quiet) { + printf("Hard link %s -> %s\n", hdr->name, + hdr->link_target); + } + return 0; + } + + if (!keep_time) { + hdr->sb.st_mtime = sqfs->fs.defaults.st_mtime; + } + + node = fstree_add_generic(&sqfs->fs, hdr->name, + &hdr->sb, hdr->link_target); + if (node == NULL) + goto fail_errno; + + if (!cfg.quiet) + printf("Packing %s\n", hdr->name); + + if (!cfg.no_xattr) { + if (copy_xattr(sqfs, node, hdr)) + return -1; + } + + if (S_ISREG(hdr->sb.st_mode)) { + if (write_file(input_file, sqfs, hdr, &node->data.file, + hdr->sb.st_size)) { + return -1; + } + } + + return 0; +fail_errno: + perror(hdr->name); + return -1; +} + +static int set_root_attribs(sqfs_writer_t *sqfs, + const tar_header_decoded_t *hdr) +{ + if (hdr->is_hard_link || !S_ISDIR(hdr->sb.st_mode)) { + fprintf(stderr, "'%s' is not a directory!\n", hdr->name); + return -1; + } + + sqfs->fs.root->uid = hdr->sb.st_uid; + sqfs->fs.root->gid = hdr->sb.st_gid; + sqfs->fs.root->mode = hdr->sb.st_mode; + + if (keep_time) + sqfs->fs.root->mod_time = hdr->sb.st_mtime; + + if (!cfg.no_xattr) { + if (copy_xattr(sqfs, sqfs->fs.root, hdr)) + return -1; + } + + return 0; +} + +int process_tarball(FILE *input_file, sqfs_writer_t *sqfs) +{ + bool skip, is_root, is_prefixed; + tar_header_decoded_t hdr; + sqfs_u64 offset, count; + sparse_map_t *m; + size_t rootlen; + int ret; + + rootlen = root_becomes == NULL ? 0 : strlen(root_becomes); + + for (;;) { + ret = read_header(input_file, &hdr); + if (ret > 0) + break; + if (ret < 0) + return -1; + + if (hdr.mtime < 0) + hdr.mtime = 0; + + if ((sqfs_u64)hdr.mtime > 0x0FFFFFFFFUL) + hdr.mtime = 0x0FFFFFFFFUL; + + hdr.sb.st_mtime = hdr.mtime; + + skip = false; + is_root = false; + is_prefixed = true; + + if (hdr.name == NULL || canonicalize_name(hdr.name) != 0) { + fprintf(stderr, "skipping '%s' (invalid name)\n", + hdr.name); + skip = true; + } + + if (root_becomes != NULL) { + if (strncmp(hdr.name, root_becomes, rootlen) == 0) { + if (hdr.name[rootlen] == '\0') { + is_root = true; + } else if (hdr.name[rootlen] != '/') { + is_prefixed = false; + } + } else { + is_prefixed = false; + } + + if (is_prefixed && !is_root) { + memmove(hdr.name, hdr.name + rootlen + 1, + strlen(hdr.name + rootlen + 1) + 1); + } + + if (is_prefixed && hdr.name[0] == '\0') { + fputs("skipping entry with empty name\n", + stderr); + skip = true; + } + } else if (hdr.name[0] == '\0') { + is_root = true; + } + + if (!is_prefixed) { + clear_header(&hdr); + continue; + } + + if (is_root) { + if (set_root_attribs(sqfs, &hdr)) + goto fail; + clear_header(&hdr); + continue; + } + + if (!skip && hdr.unknown_record) { + fprintf(stderr, "%s: unknown entry type\n", hdr.name); + skip = true; + } + + if (!skip && hdr.sparse != NULL) { + offset = hdr.sparse->offset; + count = 0; + + for (m = hdr.sparse; m != NULL; m = m->next) { + if (m->offset < offset) { + skip = true; + break; + } + offset = m->offset + m->count; + count += m->count; + } + + if (count != hdr.record_size) + skip = true; + + if (skip) { + fprintf(stderr, "%s: broken sparse " + "file layout\n", hdr.name); + } + } + + if (skip) { + if (dont_skip) + goto fail; + if (skip_entry(input_file, hdr.sb.st_size)) + goto fail; + + clear_header(&hdr); + continue; + } + + if (create_node_and_repack_data(input_file, sqfs, &hdr)) + goto fail; + + clear_header(&hdr); + } + + return 0; +fail: + clear_header(&hdr); + return -1; +} diff --git a/bin/tar2sqfs/tar2sqfs.c b/bin/tar2sqfs/tar2sqfs.c new file mode 100644 index 0000000..ae56e6b --- /dev/null +++ b/bin/tar2sqfs/tar2sqfs.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar2sqfs.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "tar2sqfs.h" + +int main(int argc, char **argv) +{ + int status = EXIT_FAILURE; + FILE *input_file = NULL; + sqfs_writer_t sqfs; + + process_args(argc, argv); + +#ifdef _WIN32 + _setmode(_fileno(stdin), _O_BINARY); + input_file = stdin; +#else + input_file = freopen(NULL, "rb", stdin); +#endif + + if (input_file == NULL) { + perror("changing stdin to binary mode"); + return EXIT_FAILURE; + } + + memset(&sqfs, 0, sizeof(sqfs)); + if (sqfs_writer_init(&sqfs, &cfg)) + return EXIT_FAILURE; + + if (process_tarball(input_file, &sqfs)) + goto out; + + if (fstree_post_process(&sqfs.fs)) + goto out; + + if (sqfs_writer_finish(&sqfs, &cfg)) + goto out; + + status = EXIT_SUCCESS; +out: + sqfs_writer_cleanup(&sqfs, status); + return status; +} diff --git a/bin/tar2sqfs/tar2sqfs.h b/bin/tar2sqfs/tar2sqfs.h new file mode 100644 index 0000000..a27a50b --- /dev/null +++ b/bin/tar2sqfs/tar2sqfs.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar2sqfs.h + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#ifndef TAR2SQFS_H +#define TAR2SQFS_H + +#include "config.h" +#include "common.h" +#include "compat.h" +#include "tar.h" + +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> + +#ifdef _WIN32 +#include <io.h> +#endif + +/* options.c */ +extern bool dont_skip; +extern bool keep_time; +extern bool no_tail_pack; +extern sqfs_writer_cfg_t cfg; +extern char *root_becomes; + +void process_args(int argc, char **argv); + +/* process_tarball.c */ +int process_tarball(FILE *input_file, sqfs_writer_t *sqfs); + +#endif /* TAR2SQFS_H */ |