diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-04-27 11:59:02 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-04-27 11:59:02 +0200 | 
| commit | 20b0d509f67dea802706cd6b80b5e20d14988931 (patch) | |
| tree | 3a87ea358b1206f6823777693d109896d6908283 /unpack | |
| parent | 9e332a2d3eddcc262476ac263e03df021b3c44b4 (diff) | |
Cleanup directory structure of the binary programs
Instead of having the binary programs in randomly named subdirectories,
move all of them to a "bin" subdirectory, similar to the utility
libraries that have subdirectories within "lib" and give the
subdirectories the propper names (e.g. have gensquashfs source in a
directory *actually* named "gensquashfs").
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'unpack')
| -rw-r--r-- | unpack/Makemodule.am | 9 | ||||
| -rw-r--r-- | unpack/describe.c | 125 | ||||
| -rw-r--r-- | unpack/dump_xattrs.c | 120 | ||||
| -rw-r--r-- | unpack/fill_files.c | 183 | ||||
| -rw-r--r-- | unpack/list_files.c | 156 | ||||
| -rw-r--r-- | unpack/options.c | 217 | ||||
| -rw-r--r-- | unpack/rdsquashfs.c | 175 | ||||
| -rw-r--r-- | unpack/rdsquashfs.h | 77 | ||||
| -rw-r--r-- | unpack/restore_fstree.c | 320 | 
9 files changed, 0 insertions, 1382 deletions
| diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am deleted file mode 100644 index 94aa0b2..0000000 --- a/unpack/Makemodule.am +++ /dev/null @@ -1,9 +0,0 @@ -rdsquashfs_SOURCES = unpack/rdsquashfs.c unpack/rdsquashfs.h -rdsquashfs_SOURCES += unpack/list_files.c unpack/options.c -rdsquashfs_SOURCES += unpack/restore_fstree.c unpack/describe.c -rdsquashfs_SOURCES += unpack/fill_files.c unpack/dump_xattrs.c -rdsquashfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -rdsquashfs_LDADD = libcommon.a libcompat.a libsquashfs.la -rdsquashfs_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) - -bin_PROGRAMS += rdsquashfs diff --git a/unpack/describe.c b/unpack/describe.c deleted file mode 100644 index d30f844..0000000 --- a/unpack/describe.c +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * describe.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -static int print_name(const sqfs_tree_node_t *n) -{ -	char *start, *ptr, *name = sqfs_tree_node_get_path(n); -	int ret; - -	if (name == NULL) { -		perror("Recovering file path of tree node"); -		return -1; -	} - -	ret = canonicalize_name(name); -	assert(ret == 0); - -	if (strchr(name, ' ') == NULL && strchr(name, '"') == NULL) { -		fputs(name, stdout); -	} else { -		fputc('"', stdout); - -		ptr = strchr(name, '"'); - -		if (ptr != NULL) { -			start = name; - -			do { -				fwrite(start, 1, ptr - start, stdout); -				fputs("\\\"", stdout); -				start = ptr + 1; -				ptr = strchr(start, '"'); -			} while (ptr != NULL); - -			fputs(start, stdout); -		} else { -			fputs(name, stdout); -		} - -		fputc('"', stdout); -	} - -	free(name); -	return 0; -} - -static void print_perm(const sqfs_tree_node_t *n) -{ -	printf(" 0%o %d %d", n->inode->base.mode & (~S_IFMT), n->uid, n->gid); -} - -static int print_simple(const char *type, const sqfs_tree_node_t *n, -			const char *extra) -{ -	printf("%s ", type); -	if (print_name(n)) -		return -1; -	print_perm(n); -	if (extra != NULL) -		printf(" %s", extra); -	fputc('\n', stdout); -	return 0; -} - -int describe_tree(const sqfs_tree_node_t *root, const char *unpack_root) -{ -	const sqfs_tree_node_t *n; - -	switch (root->inode->base.mode & S_IFMT) { -	case S_IFSOCK: -		return print_simple("sock", root, NULL); -	case S_IFLNK: -		return print_simple("slink", root, -				    (const char *)root->inode->extra); -	case S_IFIFO: -		return print_simple("pipe", root, NULL); -	case S_IFREG: -		if (unpack_root == NULL) -			return print_simple("file", root, NULL); - -		fputs("file ", stdout); -		if (print_name(root)) -			return -1; -		print_perm(root); -		printf(" %s/", unpack_root); -		if (print_name(root)) -			return -1; -		fputc('\n', stdout); -		break; -	case S_IFCHR: -	case S_IFBLK: { -		char buffer[32]; -		sqfs_u32 devno; - -		if (root->inode->base.type == SQFS_INODE_EXT_BDEV || -		    root->inode->base.type == SQFS_INODE_EXT_CDEV) { -			devno = root->inode->data.dev_ext.devno; -		} else { -			devno = root->inode->data.dev.devno; -		} - -		sprintf(buffer, "%c %d %d", -			S_ISCHR(root->inode->base.mode) ? 'c' : 'b', -			major(devno), minor(devno)); -		return print_simple("nod", root, buffer); -	} -	case S_IFDIR: -		if (root->name[0] != '\0') { -			if (print_simple("dir", root, NULL)) -				return -1; -		} - -		for (n = root->children; n != NULL; n = n->next) { -			if (describe_tree(n, unpack_root)) -				return -1; -		} -		break; -	} - -	return 0; -} diff --git a/unpack/dump_xattrs.c b/unpack/dump_xattrs.c deleted file mode 100644 index 93b0b01..0000000 --- a/unpack/dump_xattrs.c +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * dump_xattrs.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -static void print_hex(const sqfs_u8 *value, size_t len) -{ -	printf("0x"); - -	while (len--) -		printf("%02X", *(value++)); -} - -static bool is_printable(const sqfs_u8 *value, size_t len) -{ -	size_t utf8_cont = 0; -	sqfs_u8 x; - -	while (len--) { -		x = *(value++); - -		if (utf8_cont > 0) { -			if ((x & 0xC0) != 0x80) -				return false; - -			--utf8_cont; -		} else { -			if (x < 0x80) { -				if (x < 0x20) { -					if (x >= 0x07 && x <= 0x0D) -						continue; -					if (x == 0x00) -						continue; -					return false; -				} - -				if (x == 0x7F) -					return false; -			} - -			if ((x & 0xE0) == 0xC0) { -				utf8_cont = 1; -			} else if ((x & 0xF0) == 0xE0) { -				utf8_cont = 2; -			} else if ((x & 0xF8) == 0xF0) { -				utf8_cont = 3; -			} else if ((x & 0xFC) == 0xF8) { -				utf8_cont = 4; -			} else if ((x & 0xFE) == 0xFC) { -				utf8_cont = 5; -			} - -			if (utf8_cont > 0 && len < utf8_cont) -				return false; -		} -	} - -	return true; -} - -int dump_xattrs(sqfs_xattr_reader_t *xattr, const sqfs_inode_generic_t *inode) -{ -	sqfs_xattr_value_t *value; -	sqfs_xattr_entry_t *key; -	sqfs_xattr_id_t desc; -	sqfs_u32 index; -	size_t i; - -	if (xattr == NULL) -		return 0; - -	sqfs_inode_get_xattr_index(inode, &index); - -	if (index == 0xFFFFFFFF) -		return 0; - -	if (sqfs_xattr_reader_get_desc(xattr, index, &desc)) { -		fputs("Error resolving xattr index\n", stderr); -		return -1; -	} - -	if (sqfs_xattr_reader_seek_kv(xattr, &desc)) { -		fputs("Error locating xattr key-value pairs\n", stderr); -		return -1; -	} - -	for (i = 0; i < desc.count; ++i) { -		if (sqfs_xattr_reader_read_key(xattr, &key)) { -			fputs("Error reading xattr key\n", stderr); -			return -1; -		} - -		if (sqfs_xattr_reader_read_value(xattr, key, &value)) { -			fputs("Error reading xattr value\n", stderr); -			free(key); -			return -1; -		} - -		if (is_printable(key->key, key->size)) { -			printf("%s=", key->key); -		} else { -			print_hex(key->key, key->size); -		} - -		if (is_printable(value->value, value->size)) { -			printf("%s\n", value->value); -		} else { -			print_hex(value->value, value->size); -			printf("\n"); -		} - -		free(key); -		free(value); -	} - -	return 0; -} diff --git a/unpack/fill_files.c b/unpack/fill_files.c deleted file mode 100644 index b75afbf..0000000 --- a/unpack/fill_files.c +++ /dev/null @@ -1,183 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * fill_files.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" -#include "rdsquashfs.h" - -static struct file_ent { -	char *path; -	const sqfs_inode_generic_t *inode; -} *files = NULL; - -static size_t num_files = 0, max_files = 0; -static size_t block_size = 0; - -static int compare_files(const void *l, const void *r) -{ -	sqfs_u32 lhs_frag_idx, lhs_frag_off, rhs_frag_idx, rhs_frag_off; -	sqfs_u64 lhs_size, rhs_size, lhs_start, rhs_start; -	const struct file_ent *lhs = l, *rhs = r; - -	sqfs_inode_get_frag_location(lhs->inode, &lhs_frag_idx, &lhs_frag_off); -	sqfs_inode_get_file_block_start(lhs->inode, &lhs_start); -	sqfs_inode_get_file_size(lhs->inode, &lhs_size); - -	sqfs_inode_get_frag_location(rhs->inode, &rhs_frag_idx, &rhs_frag_off); -	sqfs_inode_get_file_block_start(rhs->inode, &rhs_start); -	sqfs_inode_get_file_size(rhs->inode, &rhs_size); - -	/* Files with fragments come first, ordered by ID. -	   In case of tie, files without data blocks come first, -	   and the others are ordered by start block. */ -	if ((lhs_size % block_size) && (lhs_frag_off < block_size) && -	    (lhs_frag_idx != 0xFFFFFFFF)) { -		if ((rhs_size % block_size) && (rhs_frag_off < block_size) && -		    (rhs_frag_idx != 0xFFFFFFFF)) -			return -1; - -		if (lhs_frag_idx < rhs_frag_idx) -			return -1; - -		if (lhs_frag_idx > rhs_frag_idx) -			return 1; - -		if (lhs_size < block_size) -			return (rhs_size < block_size) ? 0 : -1; - -		if (rhs_size < block_size) -			return 1; - -		goto order_by_start; -	} - -	if ((rhs_size % block_size) && (rhs_frag_off < block_size) && -	    (rhs_frag_idx != 0xFFFFFFFF)) -		return 1; - -	/* order the rest by start block */ -order_by_start: -	return lhs_start < rhs_start ? -1 : lhs_start > rhs_start ? 1 : 0; -} - -static int add_file(const sqfs_tree_node_t *node) -{ -	size_t new_sz; -	char *path; -	void *new; - -	if (num_files == max_files) { -		new_sz = max_files ? max_files * 2 : 256; -		new = realloc(files, sizeof(files[0]) * new_sz); - -		if (new == NULL) { -			perror("expanding file list"); -			return -1; -		} - -		files = new; -		max_files = new_sz; -	} - -	path = sqfs_tree_node_get_path(node); -	if (path == NULL) { -		perror("assembling file path"); -		return -1; -	} - -	if (canonicalize_name(path)) { -		fprintf(stderr, "Invalid file path '%s'\n", path); -		free(path); -		return -1; -	} - -	files[num_files].path = path; -	files[num_files].inode = node->inode; -	num_files++; -	return 0; -} - -static void clear_file_list(void) -{ -	size_t i; - -	for (i = 0; i < num_files; ++i) -		free(files[i].path); - -	free(files); -	files = NULL; -	num_files = 0; -	max_files = 0; -} - -static int gen_file_list_dfs(const sqfs_tree_node_t *n) -{ -	if (!is_filename_sane((const char *)n->name, true)) { -		fprintf(stderr, "Found an entry named '%s', skipping.\n", -			n->name); -		return 0; -	} - -	if (S_ISREG(n->inode->base.mode)) -		return add_file(n); - -	if (S_ISDIR(n->inode->base.mode)) { -		for (n = n->children; n != NULL; n = n->next) { -			if (gen_file_list_dfs(n)) -				return -1; -		} -	} - -	return 0; -} - -static int fill_files(sqfs_data_reader_t *data, int flags) -{ -	size_t i; -	FILE *fp; - -	for (i = 0; i < num_files; ++i) { -		fp = fopen(files[i].path, "wb"); -		if (fp == NULL) { -			fprintf(stderr, "unpacking %s: %s\n", -				files[i].path, strerror(errno)); -			return -1; -		} - -		if (!(flags & UNPACK_QUIET)) -			printf("unpacking %s\n", files[i].path); - -		if (sqfs_data_reader_dump(files[i].path, data, files[i].inode, -					  fp, block_size, -					  (flags & UNPACK_NO_SPARSE) == 0)) { -			fclose(fp); -			return -1; -		} - -		fflush(fp); -		fclose(fp); -	} - -	return 0; -} - -int fill_unpacked_files(size_t blk_sz, const sqfs_tree_node_t *root, -			sqfs_data_reader_t *data, int flags) -{ -	int status; - -	block_size = blk_sz; - -	if (gen_file_list_dfs(root)) { -		clear_file_list(); -		return -1; -	} - -	qsort(files, num_files, sizeof(files[0]), compare_files); - -	status = fill_files(data, flags); -	clear_file_list(); -	return status; -} diff --git a/unpack/list_files.c b/unpack/list_files.c deleted file mode 100644 index 238ffec..0000000 --- a/unpack/list_files.c +++ /dev/null @@ -1,156 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * list_files.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -static void mode_to_str(sqfs_u16 mode, char *p) -{ -	switch (mode & S_IFMT) { -	case S_IFDIR:  *(p++) = 'd'; break; -	case S_IFCHR:  *(p++) = 'c'; break; -	case S_IFBLK:  *(p++) = 'b'; break; -	case S_IFREG:  *(p++) = '-'; break; -	case S_IFLNK:  *(p++) = 'l'; break; -	case S_IFSOCK: *(p++) = 's'; break; -	case S_IFIFO:  *(p++) = 'p'; break; -	default:       *(p++) = '?'; break; -	} - -	*(p++) = (mode & S_IRUSR) ? 'r' : '-'; -	*(p++) = (mode & S_IWUSR) ? 'w' : '-'; - -	switch (mode & (S_IXUSR | S_ISUID)) { -	case S_IXUSR | S_ISUID: *(p++) = 's'; break; -	case S_IXUSR:           *(p++) = 'x'; break; -	case S_ISUID:           *(p++) = 'S'; break; -	default:                *(p++) = '-'; break; -	} - -	*(p++) = (mode & S_IRGRP) ? 'r' : '-'; -	*(p++) = (mode & S_IWGRP) ? 'w' : '-'; - -	switch (mode & (S_IXGRP | S_ISGID)) { -	case S_IXGRP | S_ISGID: *(p++) = 's'; break; -	case S_IXGRP:           *(p++) = 'x'; break; -	case S_ISGID:           *(p++) = 'S'; break; -	case 0:                 *(p++) = '-'; break; -	} - -	*(p++) = (mode & S_IROTH) ? 'r' : '-'; -	*(p++) = (mode & S_IWOTH) ? 'w' : '-'; - -	switch (mode & (S_IXOTH | S_ISVTX)) { -	case S_IXOTH | S_ISVTX: *(p++) = 't'; break; -	case S_IXOTH:           *(p++) = 'x'; break; -	case S_ISVTX:           *(p++) = 'T'; break; -	case 0:                 *(p++) = '-'; break; -	} - -	*p = '\0'; -} - -static int count_int_chars(unsigned int i) -{ -	int count = 1; - -	while (i > 10) { -		++count; -		i /= 10; -	} - -	return count; -} - -static void print_node_size(const sqfs_tree_node_t *n, char *buffer) -{ -	switch (n->inode->base.mode & S_IFMT) { -	case S_IFLNK: -		print_size(strlen((const char *)n->inode->extra), buffer, true); -		break; -	case S_IFREG: { -		sqfs_u64 size; -		sqfs_inode_get_file_size(n->inode, &size); -		print_size(size, buffer, true); -		break; -	} -	case S_IFDIR: -		if (n->inode->base.type == SQFS_INODE_EXT_DIR) { -			print_size(n->inode->data.dir_ext.size, buffer, true); -		} else { -			print_size(n->inode->data.dir.size, buffer, true); -		} -		break; -	case S_IFBLK: -	case S_IFCHR: { -		sqfs_u32 devno; - -		if (n->inode->base.type == SQFS_INODE_EXT_BDEV || -		    n->inode->base.type == SQFS_INODE_EXT_CDEV) { -			devno = n->inode->data.dev_ext.devno; -		} else { -			devno = n->inode->data.dev.devno; -		} - -		sprintf(buffer, "%u:%u", major(devno), minor(devno)); -		break; -	} -	default: -		buffer[0] = '0'; -		buffer[1] = '\0'; -		break; -	} -} - -void list_files(const sqfs_tree_node_t *node) -{ -	int i, max_uid_chars = 0, max_gid_chars = 0, max_sz_chars = 0; -	char modestr[12], sizestr[32]; -	const sqfs_tree_node_t *n; - -	if (S_ISDIR(node->inode->base.mode)) { -		for (n = node->children; n != NULL; n = n->next) { -			i = count_int_chars(n->uid); -			max_uid_chars = i > max_uid_chars ? i : max_uid_chars; - -			i = count_int_chars(n->gid); -			max_gid_chars = i > max_gid_chars ? i : max_gid_chars; - -			print_node_size(n, sizestr); -			i = strlen(sizestr); -			max_sz_chars = i > max_sz_chars ? i : max_sz_chars; -		} - -		for (n = node->children; n != NULL; n = n->next) { -			mode_to_str(n->inode->base.mode, modestr); -			print_node_size(n, sizestr); - -			printf("%s %*u/%-*u %*s %s", modestr, -			       max_uid_chars, n->uid, -			       max_gid_chars, n->gid, -			       max_sz_chars, sizestr, -			       n->name); - -			if (S_ISLNK(n->inode->base.mode)) { -				printf(" -> %s\n", -				       (const char *)n->inode->extra); -			} else { -				fputc('\n', stdout); -			} -		} -	} else { -		mode_to_str(node->inode->base.mode, modestr); -		print_node_size(node, sizestr); - -		printf("%s %u/%u %s %s", modestr, -		       node->uid, node->gid, sizestr, node->name); - -		if (S_ISLNK(node->inode->base.mode)) { -			printf(" -> %s\n", (const char *)node->inode->extra); -		} else { -			fputc('\n', stdout); -		} -	} -} diff --git a/unpack/options.c b/unpack/options.c deleted file mode 100644 index cdd19e1..0000000 --- a/unpack/options.c +++ /dev/null @@ -1,217 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * options.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -static struct option long_opts[] = { -	{ "list", required_argument, NULL, 'l' }, -	{ "cat", required_argument, NULL, 'c' }, -	{ "xattr", required_argument, NULL, 'x' }, -	{ "unpack-root", required_argument, NULL, 'p' }, -	{ "unpack-path", required_argument, NULL, 'u' }, -	{ "no-dev", no_argument, NULL, 'D' }, -	{ "no-sock", no_argument, NULL, 'S' }, -	{ "no-fifo", no_argument, NULL, 'F' }, -	{ "no-slink", no_argument, NULL, 'L' }, -	{ "no-empty-dir", no_argument, NULL, 'E' }, -	{ "no-sparse", no_argument, NULL, 'Z' }, -#ifdef HAVE_SYS_XATTR_H -	{ "set-xattr", no_argument, NULL, 'X' }, -#endif -	{ "set-times", no_argument, NULL, 'T' }, -	{ "describe", no_argument, NULL, 'd' }, -	{ "chmod", no_argument, NULL, 'C' }, -	{ "chown", no_argument, NULL, 'O' }, -	{ "quiet", no_argument, NULL, 'q' }, -	{ "help", no_argument, NULL, 'h' }, -	{ "version", no_argument, NULL, 'V' }, -	{ NULL, 0, NULL, 0 }, -}; - -static const char *short_opts = -	"l:c:u:p:x:DSFLCOEZTj:dqhV" -#ifdef HAVE_SYS_XATTR_H -	"X" -#endif -	; - -static const char *help_string = -"Usage: rdsquashfs [OPTIONS] <squashfs-file>\n" -"\n" -"View or extract the contents of a squashfs image.\n" -"\n" -"Possible options:\n" -"\n" -"  --list, -l <path>         Produce a directory listing for a given path in\n" -"                            the squashfs image.\n" -"  --cat, -c <path>          If the specified path is a regular file in the,\n" -"                            image, dump its contents to stdout.\n" -"  --xattr, -x <path>        Enumerate extended attributes associated with\n" -"                            an inode that the given path resolves to.\n" -"  --unpack-path, -u <path>  Unpack this sub directory from the image. To\n" -"                            unpack everything, simply specify /.\n" -"  --describe, -d            Produce a file listing from the image.\n" -"\n" -"  --unpack-root, -p <path>  If used with --unpack-path, this is where the\n" -"                            data unpacked to. If used with --describe, this\n" -"                            is used as a prefix for the input path of\n" -"                            regular files.\n" -"\n" -"  --no-dev, -D              Do not unpack device special files.\n" -"  --no-sock, -S             Do not unpack socket files.\n" -"  --no-fifo, -F             Do not unpack named pipes.\n" -"  --no-slink, -L            Do not unpack symbolic links.\n" -"  --no-empty-dir, -E        Do not unpack directories that would end up\n" -"                            empty after applying the above rules.\n" -"  --no-sparse, -Z           Do not create sparse files, always write zero\n" -"                            blocks to disk.\n" -#ifdef HAVE_SYS_XATTR_H -"  --set-xattr, -X           When unpacking files to disk, set the extended\n" -"                            attributes from the squashfs image.\n" -#endif -"  --set-times, -T           When unpacking files to disk, set the create\n" -"                            and modify timestamps from the squashfs image.\n" -"  --chmod, -C               Change permission flags of unpacked files to\n" -"                            those store in the squashfs image.\n" -"  --chown, -O               Change ownership of unpacked files to the\n" -"                            UID/GID set in the squashfs image.\n" -"  --quiet, -q               Do not print out progress while unpacking.\n" -"\n" -"  --help, -h                Print help text and exit.\n" -"  --version, -V             Print version information and exit.\n" -"\n"; - -static char *get_path(char *old, const char *arg) -{ -	char *path; - -	free(old); - -	path = strdup(arg); -	if (path == NULL) { -		perror("processing arguments"); -		exit(EXIT_FAILURE); -	} - -	if (canonicalize_name(path)) { -		fprintf(stderr, "Invalid path: %s\n", arg); -		free(path); -		exit(EXIT_FAILURE); -	} - -	return path; -} - -void process_command_line(options_t *opt, int argc, char **argv) -{ -	int i; - -	opt->op = OP_NONE; -	opt->rdtree_flags = 0; -	opt->flags = 0; -	opt->cmdpath = NULL; -	opt->unpack_root = NULL; -	opt->image_name = NULL; - -	for (;;) { -		i = getopt_long(argc, argv, short_opts, long_opts, NULL); -		if (i == -1) -			break; - -		switch (i) { -		case 'D': -			opt->rdtree_flags |= SQFS_TREE_NO_DEVICES; -			break; -		case 'S': -			opt->rdtree_flags |= SQFS_TREE_NO_SOCKETS; -			break; -		case 'F': -			opt->rdtree_flags |= SQFS_TREE_NO_FIFO; -			break; -		case 'L': -			opt->rdtree_flags |= SQFS_TREE_NO_SLINKS; -			break; -		case 'E': -			opt->rdtree_flags |= SQFS_TREE_NO_EMPTY; -			break; -		case 'C': -			opt->flags |= UNPACK_CHMOD; -			break; -		case 'O': -			opt->flags |= UNPACK_CHOWN; -			break; -		case 'Z': -			opt->flags |= UNPACK_NO_SPARSE; -			break; -#ifdef HAVE_SYS_XATTR_H -		case 'X': -			opt->flags |= UNPACK_SET_XATTR; -			break; -#endif -		case 'T': -			opt->flags |= UNPACK_SET_TIMES; -			break; -		case 'c': -			opt->op = OP_CAT; -			opt->cmdpath = get_path(opt->cmdpath, optarg); -			break; -		case 'd': -			opt->op = OP_DESCRIBE; -			free(opt->cmdpath); -			opt->cmdpath = NULL; -			break; -		case 'x': -			opt->op = OP_RDATTR; -			opt->cmdpath = get_path(opt->cmdpath, optarg); -			break; -		case 'l': -			opt->op = OP_LS; -			opt->cmdpath = get_path(opt->cmdpath, optarg); -			break; -		case 'p': -			opt->unpack_root = optarg; -			break; -		case 'u': -			opt->op = OP_UNPACK; -			opt->cmdpath = get_path(opt->cmdpath, optarg); -			break; -		case 'q': -			opt->flags |= UNPACK_QUIET; -			break; -		case 'h': -			fputs(help_string, stdout); -			free(opt->cmdpath); -			exit(EXIT_SUCCESS); -		case 'V': -			print_version("rdsquashfs"); -			free(opt->cmdpath); -			exit(EXIT_SUCCESS); -		default: -			goto fail_arg; -		} -	} - -	if (opt->op == OP_NONE) { -		fputs("No operation specified\n", stderr); -		goto fail_arg; -	} - -	if (opt->op == OP_LS || opt->op == OP_CAT || opt->op == OP_RDATTR) { -		opt->rdtree_flags |= SQFS_TREE_NO_RECURSE; -	} - -	if (optind >= argc) { -		fputs("Missing image argument\n", stderr); -		goto fail_arg; -	} - -	opt->image_name = argv[optind++]; -	return; -fail_arg: -	fputs("Try `rdsquashfs --help' for more information.\n", stderr); -	free(opt->cmdpath); -	exit(EXIT_FAILURE); -} diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c deleted file mode 100644 index fa2bbb4..0000000 --- a/unpack/rdsquashfs.c +++ /dev/null @@ -1,175 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * rdsquashfs.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -int main(int argc, char **argv) -{ -	sqfs_xattr_reader_t *xattr = NULL; -	sqfs_compressor_config_t cfg; -	int status = EXIT_FAILURE; -	sqfs_data_reader_t *data; -	sqfs_dir_reader_t *dirrd; -	sqfs_compressor_t *cmp; -	sqfs_id_table_t *idtbl; -	sqfs_tree_node_t *n; -	sqfs_super_t super; -	sqfs_file_t *file; -	options_t opt; -	int ret; - -	process_command_line(&opt, argc, argv); - -	file = sqfs_open_file(opt.image_name, SQFS_FILE_OPEN_READ_ONLY); -	if (file == NULL) { -		perror(opt.image_name); -		goto out_cmd; -	} - -	ret = sqfs_super_read(&super, file); -	if (ret) { -		sqfs_perror(opt.image_name, "reading super block", ret); -		goto out_file; -	} - -	sqfs_compressor_config_init(&cfg, super.compression_id, -				    super.block_size, -				    SQFS_COMP_FLAG_UNCOMPRESS); - -	ret = sqfs_compressor_create(&cfg, &cmp); - -#ifdef WITH_LZO -	if (super.compression_id == SQFS_COMP_LZO && ret != 0) -		ret = lzo_compressor_create(&cfg, &cmp); -#endif - -	if (ret != 0) { -		sqfs_perror(opt.image_name, "creating compressor", ret); -		goto out_file; -	} - -	if (!(super.flags & SQFS_FLAG_NO_XATTRS)) { -		xattr = sqfs_xattr_reader_create(0); -		if (xattr == NULL) { -			sqfs_perror(opt.image_name, "creating xattr reader", -				    SQFS_ERROR_ALLOC); -			goto out_cmp; -		} - -		ret = sqfs_xattr_reader_load(xattr, &super, file, cmp); -		if (ret) { -			sqfs_perror(opt.image_name, "loading xattr table", -				    ret); -			goto out_xr; -		} -	} - -	idtbl = sqfs_id_table_create(0); -	if (idtbl == NULL) { -		sqfs_perror(opt.image_name, "creating ID table", -			    SQFS_ERROR_ALLOC); -		goto out_xr; -	} - -	ret = sqfs_id_table_read(idtbl, file, &super, cmp); -	if (ret) { -		sqfs_perror(opt.image_name, "loading ID table", ret); -		goto out_id; -	} - -	dirrd = sqfs_dir_reader_create(&super, cmp, file); -	if (dirrd == NULL) { -		sqfs_perror(opt.image_name, "creating dir reader", -			    SQFS_ERROR_ALLOC); -		goto out_id; -	} - -	data = sqfs_data_reader_create(file, super.block_size, cmp); -	if (data == NULL) { -		sqfs_perror(opt.image_name, "creating data reader", -			    SQFS_ERROR_ALLOC); -		goto out_dr; -	} - -	ret = sqfs_data_reader_load_fragment_table(data, &super); -	if (ret) { -		sqfs_perror(opt.image_name, "loading fragment table", ret); -		goto out_data; -	} - -	ret = sqfs_dir_reader_get_full_hierarchy(dirrd, idtbl, opt.cmdpath, -						 opt.rdtree_flags, &n); -	if (ret) { -		sqfs_perror(opt.image_name, "reading filesystem tree", ret); -		goto out_data; -	} - -	switch (opt.op) { -	case OP_LS: -		list_files(n); -		break; -	case OP_CAT: -		if (!S_ISREG(n->inode->base.mode)) { -			fprintf(stderr, "/%s: not a regular file\n", -				opt.cmdpath); -			goto out; -		} - -		if (sqfs_data_reader_dump(opt.cmdpath, data, n->inode, -					  stdout, super.block_size, false)) { -			goto out; -		} -		break; -	case OP_UNPACK: -		if (opt.unpack_root != NULL) { -			if (mkdir_p(opt.unpack_root)) -				goto out; - -			if (chdir(opt.unpack_root)) { -				perror(opt.unpack_root); -				goto out; -			} -		} - -		if (restore_fstree(n, opt.flags)) -			goto out; - -		if (fill_unpacked_files(super.block_size, n, data, opt.flags)) -			goto out; - -		if (update_tree_attribs(xattr, n, opt.flags)) -			goto out; -		break; -	case OP_DESCRIBE: -		if (describe_tree(n, opt.unpack_root)) -			goto out; -		break; -	case OP_RDATTR: -		if (dump_xattrs(xattr, n->inode)) -			goto out; -		break; -	} - -	status = EXIT_SUCCESS; -out: -	sqfs_dir_tree_destroy(n); -out_data: -	sqfs_destroy(data); -out_dr: -	sqfs_destroy(dirrd); -out_id: -	sqfs_destroy(idtbl); -out_xr: -	if (xattr != NULL) -		sqfs_destroy(xattr); -out_cmp: -	sqfs_destroy(cmp); -out_file: -	sqfs_destroy(file); -out_cmd: -	free(opt.cmdpath); -	return status; -} diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h deleted file mode 100644 index 17c0a85..0000000 --- a/unpack/rdsquashfs.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * rdsquashfs.h - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#ifndef RDSQUASHFS_H -#define RDSQUASHFS_H - -#include "config.h" -#include "common.h" -#include "fstree.h" - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#endif -#ifdef HAVE_SYS_XATTR_H -#include <sys/xattr.h> - -#if defined(__APPLE__) && defined(__MACH__) -#define lsetxattr(path, name, value, size, flags) \ -	setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW) -#endif -#endif -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <stdio.h> - -enum UNPACK_FLAGS { -	UNPACK_CHMOD = 0x01, -	UNPACK_CHOWN = 0x02, -	UNPACK_QUIET = 0x04, -	UNPACK_NO_SPARSE = 0x08, -	UNPACK_SET_XATTR = 0x10, -	UNPACK_SET_TIMES = 0x20, -}; - -enum { -	OP_NONE = 0, -	OP_LS, -	OP_CAT, -	OP_UNPACK, -	OP_DESCRIBE, -	OP_RDATTR, -}; - -typedef struct { -	int op; -	int rdtree_flags; -	int flags; -	char *cmdpath; -	const char *unpack_root; -	const char *image_name; -} options_t; - -void list_files(const sqfs_tree_node_t *node); - -int restore_fstree(sqfs_tree_node_t *root, int flags); - -int update_tree_attribs(sqfs_xattr_reader_t *xattr, -			const sqfs_tree_node_t *root, int flags); - -int fill_unpacked_files(size_t blk_sz, const sqfs_tree_node_t *root, -			sqfs_data_reader_t *data, int flags); - -int describe_tree(const sqfs_tree_node_t *root, const char *unpack_root); - -int dump_xattrs(sqfs_xattr_reader_t *xattr, const sqfs_inode_generic_t *inode); - -void process_command_line(options_t *opt, int argc, char **argv); - -#endif /* RDSQUASHFS_H */ diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c deleted file mode 100644 index 8f99439..0000000 --- a/unpack/restore_fstree.c +++ /dev/null @@ -1,320 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * restore_fstree.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "rdsquashfs.h" - -#ifdef _WIN32 -static int create_node(const sqfs_tree_node_t *n, const char *name) -{ -	WCHAR *wpath; -	HANDLE fh; - -	wpath = path_to_windows(name); -	if (wpath == NULL) -		return -1; - -	switch (n->inode->base.mode & S_IFMT) { -	case S_IFDIR: -		if (!CreateDirectoryW(wpath, NULL)) -			goto fail; -		break; -	case S_IFREG: -		fh = CreateFileW(wpath, GENERIC_READ, -				 FILE_SHARE_READ | FILE_SHARE_WRITE, -				 NULL, CREATE_NEW, 0, NULL); - -		if (fh == INVALID_HANDLE_VALUE) -			goto fail; - -		CloseHandle(fh); -		break; -	default: -		break; -	} - -	free(wpath); -	return 0; -fail: -	fprintf(stderr, "Creating %s: %ld\n", name, GetLastError()); -	free(wpath); -	return -1; -} -#else -static int create_node(const sqfs_tree_node_t *n, const char *name) -{ -	sqfs_u32 devno; -	int fd; - -	switch (n->inode->base.mode & S_IFMT) { -	case S_IFDIR: -		if (mkdir(name, 0755) && errno != EEXIST) { -			fprintf(stderr, "mkdir %s: %s\n", -				name, strerror(errno)); -			return -1; -		} -		break; -	case S_IFLNK: -		if (symlink((const char *)n->inode->extra, name)) { -			fprintf(stderr, "ln -s %s %s: %s\n", -				(const char *)n->inode->extra, name, -				strerror(errno)); -			return -1; -		} -		break; -	case S_IFSOCK: -	case S_IFIFO: -		if (mknod(name, (n->inode->base.mode & S_IFMT) | 0700, 0)) { -			fprintf(stderr, "creating %s: %s\n", -				name, strerror(errno)); -			return -1; -		} -		break; -	case S_IFBLK: -	case S_IFCHR: -		if (n->inode->base.type == SQFS_INODE_EXT_BDEV || -		    n->inode->base.type == SQFS_INODE_EXT_CDEV) { -			devno = n->inode->data.dev_ext.devno; -		} else { -			devno = n->inode->data.dev.devno; -		} - -		if (mknod(name, n->inode->base.mode & S_IFMT, devno)) { -			fprintf(stderr, "creating device %s: %s\n", -				name, strerror(errno)); -			return -1; -		} -		break; -	case S_IFREG: -		fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600); - -		if (fd < 0) { -			fprintf(stderr, "creating %s: %s\n", -				name, strerror(errno)); -			return -1; -		} - -		close(fd); -		break; -	default: -		break; -	} - -	return 0; -} -#endif - -static int create_node_dfs(const sqfs_tree_node_t *n, int flags) -{ -	const sqfs_tree_node_t *c; -	char *name; -	int ret; - -	if (!is_filename_sane((const char *)n->name, true)) { -		fprintf(stderr, "Found an entry named '%s', skipping.\n", -			n->name); -		return 0; -	} - -	name = sqfs_tree_node_get_path(n); -	if (name == NULL) { -		fprintf(stderr, "Constructing full path for '%s': %s\n", -			(const char *)n->name, strerror(errno)); -		return -1; -	} - -	ret = canonicalize_name(name); -	assert(ret == 0); - -	if (!(flags & UNPACK_QUIET)) -		printf("creating %s\n", name); - -	ret = create_node(n, name); -	free(name); -	if (ret) -		return -1; - -	if (S_ISDIR(n->inode->base.mode)) { -		for (c = n->children; c != NULL; c = c->next) { -			if (create_node_dfs(c, flags)) -				return -1; -		} -	} -	return 0; -} - -#ifdef HAVE_SYS_XATTR_H -static int set_xattr(const char *path, sqfs_xattr_reader_t *xattr, -		     const sqfs_tree_node_t *n) -{ -	sqfs_xattr_value_t *value; -	sqfs_xattr_entry_t *key; -	sqfs_xattr_id_t desc; -	sqfs_u32 index; -	size_t i; -	int ret; - -	sqfs_inode_get_xattr_index(n->inode, &index); - -	if (index == 0xFFFFFFFF) -		return 0; - -	if (sqfs_xattr_reader_get_desc(xattr, index, &desc)) { -		fputs("Error resolving xattr index\n", stderr); -		return -1; -	} - -	if (sqfs_xattr_reader_seek_kv(xattr, &desc)) { -		fputs("Error locating xattr key-value pairs\n", stderr); -		return -1; -	} - -	for (i = 0; i < desc.count; ++i) { -		if (sqfs_xattr_reader_read_key(xattr, &key)) { -			fputs("Error reading xattr key\n", stderr); -			return -1; -		} - -		if (sqfs_xattr_reader_read_value(xattr, key, &value)) { -			fputs("Error reading xattr value\n", stderr); -			free(key); -			return -1; -		} - -		ret = lsetxattr(path, (const char *)key->key, -				value->value, value->size, 0); -		if (ret) { -			fprintf(stderr, "setting xattr '%s' on %s: %s\n", -				key->key, path, strerror(errno)); -		} - -		free(key); -		free(value); -		if (ret) -			return -1; -	} - -	return 0; -} -#endif - -static int set_attribs(sqfs_xattr_reader_t *xattr, -		       const sqfs_tree_node_t *n, int flags) -{ -	const sqfs_tree_node_t *c; -	char *path; -	int ret; - -	if (!is_filename_sane((const char *)n->name, true)) -		return 0; - -	if (S_ISDIR(n->inode->base.mode)) { -		for (c = n->children; c != NULL; c = c->next) { -			if (set_attribs(xattr, c, flags)) -				return -1; -		} -	} - -	path = sqfs_tree_node_get_path(n); -	if (path == NULL) { -		fprintf(stderr, "Reconstructing full path: %s\n", -			strerror(errno)); -		return -1; -	} - -	ret = canonicalize_name(path); -	assert(ret == 0); - -#ifdef HAVE_SYS_XATTR_H -	if ((flags & UNPACK_SET_XATTR) && xattr != NULL) { -		if (set_xattr(path, xattr, n)) -			goto fail; -	} -#endif - -#ifndef _WIN32 -	if (flags & UNPACK_SET_TIMES) { -		struct timespec times[2]; - -		memset(times, 0, sizeof(times)); -		times[0].tv_sec = n->inode->base.mod_time; -		times[1].tv_sec = n->inode->base.mod_time; - -		if (utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW)) { -			fprintf(stderr, "setting timestamp on %s: %s\n", -				path, strerror(errno)); -			goto fail; -		} -	} -#endif -	if (flags & UNPACK_CHOWN) { -		if (fchownat(AT_FDCWD, path, n->uid, n->gid, -			     AT_SYMLINK_NOFOLLOW)) { -			fprintf(stderr, "chown %s: %s\n", -				path, strerror(errno)); -			goto fail; -		} -	} - -	if (flags & UNPACK_CHMOD && !S_ISLNK(n->inode->base.mode)) { -		if (fchmodat(AT_FDCWD, path, -			     n->inode->base.mode & ~S_IFMT, 0)) { -			fprintf(stderr, "chmod %s: %s\n", -				path, strerror(errno)); -			goto fail; -		} -	} - -	free(path); -	return 0; -fail: -	free(path); -	return -1; -} - -int restore_fstree(sqfs_tree_node_t *root, int flags) -{ -	sqfs_tree_node_t *n, *old_parent; - -	/* make sure fstree_get_path() stops at this node */ -	old_parent = root->parent; -	root->parent = NULL; - -	if (S_ISDIR(root->inode->base.mode)) { -		for (n = root->children; n != NULL; n = n->next) { -			if (create_node_dfs(n, flags)) -				return -1; -		} -	} else { -		if (create_node_dfs(root, flags)) -			return -1; -	} - -	root->parent = old_parent; -	return 0; -} - -int update_tree_attribs(sqfs_xattr_reader_t *xattr, -			const sqfs_tree_node_t *root, int flags) -{ -	const sqfs_tree_node_t *n; - -	if ((flags & (UNPACK_CHOWN | UNPACK_CHMOD | -		      UNPACK_SET_TIMES | UNPACK_SET_XATTR)) == 0) { -		return 0; -	} - -	if (S_ISDIR(root->inode->base.mode)) { -		for (n = root->children; n != NULL; n = n->next) { -			if (set_attribs(xattr, n, flags)) -				return -1; -		} -	} else { -		if (set_attribs(xattr, root, flags)) -			return -1; -	} - -	return 0; -} | 
