diff options
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 */ | 
