diff options
Diffstat (limited to 'mkfs')
| -rw-r--r-- | mkfs/Makemodule.am | 2 | ||||
| -rw-r--r-- | mkfs/meta.c | 296 | ||||
| -rw-r--r-- | mkfs/mkfs.h | 3 | ||||
| -rw-r--r-- | mkfs/write_inode.c | 290 | 
4 files changed, 298 insertions, 293 deletions
| diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index 8691fd7..55f30c7 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -1,6 +1,6 @@  gensquashfs_SOURCES = mkfs/mkfs.c mkfs/mkfs.h mkfs/block.c  gensquashfs_SOURCES += mkfs/options.c mkfs/meta.c mkfs/xattr.c -gensquashfs_SOURCES += mkfs/write_dir.c +gensquashfs_SOURCES += mkfs/write_dir.c mkfs/write_inode.c  gensquashfs_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a  gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/mkfs/meta.c b/mkfs/meta.c index 9c305b1..2d969a3 100644 --- a/mkfs/meta.c +++ b/mkfs/meta.c @@ -1,295 +1,7 @@  /* SPDX-License-Identifier: GPL-3.0-or-later */ -#include "meta_writer.h"  #include "mkfs.h"  #include "util.h" -#include <assert.h> -#include <endian.h> - -static int get_type(tree_node_t *node) -{ -	int type; - -	switch (node->mode & S_IFMT) { -	case S_IFSOCK: type = SQFS_INODE_SOCKET; break; -	case S_IFIFO:  type = SQFS_INODE_FIFO; break; -	case S_IFLNK:  type = SQFS_INODE_SLINK; break; -	case S_IFBLK:  type = SQFS_INODE_BDEV; break; -	case S_IFCHR:  type = SQFS_INODE_CDEV; break; -	case S_IFDIR:  type = SQFS_INODE_DIR; break; -	case S_IFREG:  type = SQFS_INODE_FILE; break; -	default: -		assert(0); -	} - -	if (node->xattr != NULL) -		type = SQFS_INODE_EXT_TYPE(type); - -	return type; -} - -static size_t hard_link_count(tree_node_t *n) -{ -	size_t count; - -	if (S_ISDIR(n->mode)) { -		count = 2; - -		for (n = n->data.dir->children; n != NULL; n = n->next) -			++count; - -		return count; -	} - -	return 1; -} - -static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm, -		       tree_node_t *node) -{ -	dir_index_t *diridx = NULL; -	uint16_t uid_idx, gid_idx; -	file_info_t *fi = NULL; -	dir_info_t *di = NULL; -	uint32_t bs, offset; -	sqfs_inode_t base; -	uint64_t i, block; -	int type; - -	if (id_table_id_to_index(&info->idtbl, node->uid, &uid_idx)) -		return -1; - -	if (id_table_id_to_index(&info->idtbl, node->gid, &gid_idx)) -		return -1; - -	meta_writer_get_position(im, &block, &offset); -	node->inode_ref = (block << 16) | offset; - -	type = get_type(node); - -	if (S_ISDIR(node->mode)) { -		di = node->data.dir; - -		if (write_dir(dm, di, &diridx)) -			return -1; - -		if ((di->start_block) > 0xFFFFFFFFUL || di->size > 0xFFFF || -		    node->xattr != NULL) { -			type = SQFS_INODE_EXT_DIR; -		} else { -			type = SQFS_INODE_DIR; -			free(diridx); -			diridx = NULL; -		} -	} else if (S_ISREG(node->mode)) { -		fi = node->data.file; - -		if (fi->startblock > 0xFFFFFFFFUL || fi->size > 0xFFFFFFFFUL || -		    hard_link_count(node) > 1) { -			type = SQFS_INODE_EXT_FILE; -		} -	} - -	base.type = htole16(type); -	base.mode = htole16(node->mode); -	base.uid_idx = htole16(uid_idx); -	base.gid_idx = htole16(gid_idx); -	base.mod_time = htole32(info->opt.def_mtime); -	base.inode_number = htole32(node->inode_num); - -	if (meta_writer_append(im, &base, sizeof(base))) { -		free(diridx); -		return -1; -	} - -	switch (type) { -	case SQFS_INODE_FIFO: -	case SQFS_INODE_SOCKET: { -		sqfs_inode_ipc_t ipc = { -			.nlink = hard_link_count(node), -		}; - -		return meta_writer_append(im, &ipc, sizeof(ipc)); -	} -	case SQFS_INODE_EXT_FIFO: -	case SQFS_INODE_EXT_SOCKET: { -		sqfs_inode_ipc_ext_t ipc = { -			.nlink = hard_link_count(node), -			.xattr_idx = htole32(0xFFFFFFFF), -		}; - -		if (node->xattr != NULL) -			ipc.xattr_idx = htole32(node->xattr->index); - -		return meta_writer_append(im, &ipc, sizeof(ipc)); -	} -	case SQFS_INODE_SLINK: { -		sqfs_inode_slink_t slink = { -			.nlink = htole32(hard_link_count(node)), -			.target_size = htole32(strlen(node->data.slink_target)), -		}; - -		if (meta_writer_append(im, &slink, sizeof(slink))) -			return -1; -		if (meta_writer_append(im, node->data.slink_target, -				       le32toh(slink.target_size))) { -			return -1; -		} -		break; -	} -	case SQFS_INODE_EXT_SLINK: { -		sqfs_inode_slink_t slink = { -			.nlink = htole32(hard_link_count(node)), -			.target_size = htole32(strlen(node->data.slink_target)), -		}; -		uint32_t xattr = htole32(0xFFFFFFFF); - -		if (node->xattr != NULL) -			xattr = htole32(node->xattr->index); - -		if (meta_writer_append(im, &slink, sizeof(slink))) -			return -1; -		if (meta_writer_append(im, node->data.slink_target, -				       le32toh(slink.target_size))) { -			return -1; -		} -		if (meta_writer_append(im, &xattr, sizeof(xattr))) -			return -1; -		break; -	} -	case SQFS_INODE_BDEV: -	case SQFS_INODE_CDEV: { -		sqfs_inode_dev_t dev = { -			.nlink = htole32(hard_link_count(node)), -			.devno = htole32(node->data.devno), -		}; - -		return meta_writer_append(im, &dev, sizeof(dev)); -	} -	case SQFS_INODE_EXT_BDEV: -	case SQFS_INODE_EXT_CDEV: { -		sqfs_inode_dev_ext_t dev = { -			.nlink = htole32(hard_link_count(node)), -			.devno = htole32(node->data.devno), -			.xattr_idx = htole32(0xFFFFFFFF), -		}; - -		if (node->xattr != NULL) -			dev.xattr_idx = htole32(node->xattr->index); - -		return meta_writer_append(im, &dev, sizeof(dev)); -	} - -	case SQFS_INODE_EXT_FILE: { -		sqfs_inode_file_ext_t ext = { -			.blocks_start = htole64(fi->startblock), -			.file_size = htole64(fi->size), -			.sparse = htole64(0xFFFFFFFFFFFFFFFFUL), -			.nlink = htole32(hard_link_count(node)), -			.fragment_idx = htole32(fi->fragment), -			.fragment_offset = htole32(fi->fragment_offset), -			.xattr_idx = htole32(0xFFFFFFFF), -		}; - -		if (node->xattr != NULL) -			ext.xattr_idx = htole32(node->xattr->index); - -		if (meta_writer_append(im, &ext, sizeof(ext))) -			return -1; -		goto out_file_blocks; -	} -	case SQFS_INODE_FILE: { -		sqfs_inode_file_t reg = { -			.blocks_start = htole32(fi->startblock), -			.fragment_index = htole32(fi->fragment), -			.fragment_offset = htole32(fi->fragment_offset), -			.file_size = htole32(fi->size), -		}; - -		if (meta_writer_append(im, ®, sizeof(reg))) -			return -1; -		goto out_file_blocks; -	} -	case SQFS_INODE_DIR: { -		sqfs_inode_dir_t dir = { -			.start_block = htole32(node->data.dir->start_block), -			.nlink = htole32(hard_link_count(node)), -			.size = htole16(node->data.dir->size), -			.offset = htole16(node->data.dir->block_offset), -			.parent_inode = node->parent ? -				htole32(node->parent->inode_num) : htole32(1), -		}; - -		return meta_writer_append(im, &dir, sizeof(dir)); -	} -	case SQFS_INODE_EXT_DIR: { -		sqfs_dir_index_t idx; -		size_t i; -		sqfs_inode_dir_ext_t ext = { -			.nlink = htole32(hard_link_count(node)), -			.size = htole32(node->data.dir->size), -			.start_block = htole32(node->data.dir->start_block), -			.parent_inode = node->parent ? -				htole32(node->parent->inode_num) : htole32(1), -			.inodex_count = htole32(0), -			.offset = htole16(node->data.dir->block_offset), -			.xattr_idx = htole32(0xFFFFFFFF), -		}; - -		if (node->xattr != NULL) -			ext.xattr_idx = htole32(node->xattr->index); - -		if (meta_writer_append(im, &ext, sizeof(ext))) { -			free(diridx); -			return -1; -		} - -		/* HACK: truncated index for empty directories */ -		if (node->data.dir->size == 0) -			break; - -		ext.inodex_count = htole32(diridx->num_nodes - 1); - -		for (i = 0; i < diridx->num_nodes; ++i) { -			idx.start_block = htole32(diridx->idx_nodes[i].block); - -			idx.index = diridx->idx_nodes[i].offset; -			idx.index -= node->data.dir->block_offset; -			idx.index = htole32(idx.index); - -			idx.size = strlen(diridx->idx_nodes[i].node->name) - 1; -			idx.size = htole32(idx.size); - -			if (meta_writer_append(im, &idx, sizeof(idx))) { -				free(diridx); -				return -1; -			} - -			if (meta_writer_append(im, -					       diridx->idx_nodes[i].node->name, -					       le32toh(idx.size) + 1)) { -				free(diridx); -				return -1; -			} -		} - -		free(diridx); -		break; -	} -	default: -		assert(0); -	} -	return 0; -out_file_blocks: -	for (i = 0; i < fi->size / info->super.block_size; ++i) { -		bs = htole32(fi->blocksizes[i]); - -		if (meta_writer_append(im, &bs, sizeof(bs))) -			return -1; -	} -	return 0; -} -  int sqfs_write_inodes(sqfs_info_t *info)  {  	meta_writer_t *im, *dm; @@ -317,10 +29,10 @@ int sqfs_write_inodes(sqfs_info_t *info)  	if (dm == NULL)  		goto fail_im; -	for (i = 0; i < info->fs.inode_tbl_size; ++i) { -		if (info->fs.inode_table[i] != NULL) { -			if (write_inode(info, im, dm, info->fs.inode_table[i])) -				goto fail; +	for (i = 2; i < info->fs.inode_tbl_size; ++i) { +		if (write_inode(&info->fs, &info->idtbl, im, dm, +				info->fs.inode_table[i])) { +			goto fail;  		}  	} diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index e3e3c5d..13eb690 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -79,4 +79,7 @@ int write_xattr(sqfs_info_t *info);  int write_dir(meta_writer_t *dm, dir_info_t *dir, dir_index_t **index); +int write_inode(fstree_t *fs, id_table_t *idtbl, meta_writer_t *im, +		meta_writer_t *dm, tree_node_t *node); +  #endif /* MKFS_H */ diff --git a/mkfs/write_inode.c b/mkfs/write_inode.c new file mode 100644 index 0000000..6890cb6 --- /dev/null +++ b/mkfs/write_inode.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "mkfs.h" +#include "util.h" + +#include <assert.h> +#include <endian.h> + +static int get_type(tree_node_t *node) +{ +	int type; + +	switch (node->mode & S_IFMT) { +	case S_IFSOCK: type = SQFS_INODE_SOCKET; break; +	case S_IFIFO:  type = SQFS_INODE_FIFO; break; +	case S_IFLNK:  type = SQFS_INODE_SLINK; break; +	case S_IFBLK:  type = SQFS_INODE_BDEV; break; +	case S_IFCHR:  type = SQFS_INODE_CDEV; break; +	case S_IFDIR:  type = SQFS_INODE_DIR; break; +	case S_IFREG:  type = SQFS_INODE_FILE; break; +	default: +		assert(0); +	} + +	if (node->xattr != NULL) +		type = SQFS_INODE_EXT_TYPE(type); + +	return type; +} + +static size_t hard_link_count(tree_node_t *n) +{ +	size_t count; + +	if (S_ISDIR(n->mode)) { +		count = 2; + +		for (n = n->data.dir->children; n != NULL; n = n->next) +			++count; + +		return count; +	} + +	return 1; +} + +int write_inode(fstree_t *fs, id_table_t *idtbl, meta_writer_t *im, +		meta_writer_t *dm, tree_node_t *node) +{ +	dir_index_t *diridx = NULL; +	uint16_t uid_idx, gid_idx; +	file_info_t *fi = NULL; +	dir_info_t *di = NULL; +	uint32_t bs, offset; +	sqfs_inode_t base; +	uint64_t i, block; +	int type; + +	if (id_table_id_to_index(idtbl, node->uid, &uid_idx)) +		return -1; + +	if (id_table_id_to_index(idtbl, node->gid, &gid_idx)) +		return -1; + +	meta_writer_get_position(im, &block, &offset); +	node->inode_ref = (block << 16) | offset; + +	type = get_type(node); + +	if (S_ISDIR(node->mode)) { +		di = node->data.dir; + +		if (write_dir(dm, di, &diridx)) +			return -1; + +		if ((di->start_block) > 0xFFFFFFFFUL || di->size > 0xFFFF || +		    node->xattr != NULL) { +			type = SQFS_INODE_EXT_DIR; +		} else { +			type = SQFS_INODE_DIR; +			free(diridx); +			diridx = NULL; +		} +	} else if (S_ISREG(node->mode)) { +		fi = node->data.file; + +		if (fi->startblock > 0xFFFFFFFFUL || fi->size > 0xFFFFFFFFUL || +		    hard_link_count(node) > 1) { +			type = SQFS_INODE_EXT_FILE; +		} +	} + +	base.type = htole16(type); +	base.mode = htole16(node->mode); +	base.uid_idx = htole16(uid_idx); +	base.gid_idx = htole16(gid_idx); +	base.mod_time = htole32(fs->default_mtime); +	base.inode_number = htole32(node->inode_num); + +	if (meta_writer_append(im, &base, sizeof(base))) { +		free(diridx); +		return -1; +	} + +	switch (type) { +	case SQFS_INODE_FIFO: +	case SQFS_INODE_SOCKET: { +		sqfs_inode_ipc_t ipc = { +			.nlink = hard_link_count(node), +		}; + +		return meta_writer_append(im, &ipc, sizeof(ipc)); +	} +	case SQFS_INODE_EXT_FIFO: +	case SQFS_INODE_EXT_SOCKET: { +		sqfs_inode_ipc_ext_t ipc = { +			.nlink = hard_link_count(node), +			.xattr_idx = htole32(0xFFFFFFFF), +		}; + +		if (node->xattr != NULL) +			ipc.xattr_idx = htole32(node->xattr->index); + +		return meta_writer_append(im, &ipc, sizeof(ipc)); +	} +	case SQFS_INODE_SLINK: { +		sqfs_inode_slink_t slink = { +			.nlink = htole32(hard_link_count(node)), +			.target_size = htole32(strlen(node->data.slink_target)), +		}; + +		if (meta_writer_append(im, &slink, sizeof(slink))) +			return -1; +		if (meta_writer_append(im, node->data.slink_target, +				       le32toh(slink.target_size))) { +			return -1; +		} +		break; +	} +	case SQFS_INODE_EXT_SLINK: { +		sqfs_inode_slink_t slink = { +			.nlink = htole32(hard_link_count(node)), +			.target_size = htole32(strlen(node->data.slink_target)), +		}; +		uint32_t xattr = htole32(0xFFFFFFFF); + +		if (node->xattr != NULL) +			xattr = htole32(node->xattr->index); + +		if (meta_writer_append(im, &slink, sizeof(slink))) +			return -1; +		if (meta_writer_append(im, node->data.slink_target, +				       le32toh(slink.target_size))) { +			return -1; +		} +		if (meta_writer_append(im, &xattr, sizeof(xattr))) +			return -1; +		break; +	} +	case SQFS_INODE_BDEV: +	case SQFS_INODE_CDEV: { +		sqfs_inode_dev_t dev = { +			.nlink = htole32(hard_link_count(node)), +			.devno = htole32(node->data.devno), +		}; + +		return meta_writer_append(im, &dev, sizeof(dev)); +	} +	case SQFS_INODE_EXT_BDEV: +	case SQFS_INODE_EXT_CDEV: { +		sqfs_inode_dev_ext_t dev = { +			.nlink = htole32(hard_link_count(node)), +			.devno = htole32(node->data.devno), +			.xattr_idx = htole32(0xFFFFFFFF), +		}; + +		if (node->xattr != NULL) +			dev.xattr_idx = htole32(node->xattr->index); + +		return meta_writer_append(im, &dev, sizeof(dev)); +	} + +	case SQFS_INODE_EXT_FILE: { +		sqfs_inode_file_ext_t ext = { +			.blocks_start = htole64(fi->startblock), +			.file_size = htole64(fi->size), +			.sparse = htole64(0xFFFFFFFFFFFFFFFFUL), +			.nlink = htole32(hard_link_count(node)), +			.fragment_idx = htole32(fi->fragment), +			.fragment_offset = htole32(fi->fragment_offset), +			.xattr_idx = htole32(0xFFFFFFFF), +		}; + +		if (node->xattr != NULL) +			ext.xattr_idx = htole32(node->xattr->index); + +		if (meta_writer_append(im, &ext, sizeof(ext))) +			return -1; +		goto out_file_blocks; +	} +	case SQFS_INODE_FILE: { +		sqfs_inode_file_t reg = { +			.blocks_start = htole32(fi->startblock), +			.fragment_index = htole32(fi->fragment), +			.fragment_offset = htole32(fi->fragment_offset), +			.file_size = htole32(fi->size), +		}; + +		if (meta_writer_append(im, ®, sizeof(reg))) +			return -1; +		goto out_file_blocks; +	} +	case SQFS_INODE_DIR: { +		sqfs_inode_dir_t dir = { +			.start_block = htole32(node->data.dir->start_block), +			.nlink = htole32(hard_link_count(node)), +			.size = htole16(node->data.dir->size), +			.offset = htole16(node->data.dir->block_offset), +			.parent_inode = node->parent ? +				htole32(node->parent->inode_num) : htole32(1), +		}; + +		return meta_writer_append(im, &dir, sizeof(dir)); +	} +	case SQFS_INODE_EXT_DIR: { +		sqfs_dir_index_t idx; +		size_t i; +		sqfs_inode_dir_ext_t ext = { +			.nlink = htole32(hard_link_count(node)), +			.size = htole32(node->data.dir->size), +			.start_block = htole32(node->data.dir->start_block), +			.parent_inode = node->parent ? +				htole32(node->parent->inode_num) : htole32(1), +			.inodex_count = htole32(0), +			.offset = htole16(node->data.dir->block_offset), +			.xattr_idx = htole32(0xFFFFFFFF), +		}; + +		if (node->xattr != NULL) +			ext.xattr_idx = htole32(node->xattr->index); + +		if (meta_writer_append(im, &ext, sizeof(ext))) { +			free(diridx); +			return -1; +		} + +		/* HACK: truncated index for empty directories */ +		if (node->data.dir->size == 0) +			break; + +		ext.inodex_count = htole32(diridx->num_nodes - 1); + +		for (i = 0; i < diridx->num_nodes; ++i) { +			idx.start_block = htole32(diridx->idx_nodes[i].block); + +			idx.index = diridx->idx_nodes[i].offset; +			idx.index -= node->data.dir->block_offset; +			idx.index = htole32(idx.index); + +			idx.size = strlen(diridx->idx_nodes[i].node->name) - 1; +			idx.size = htole32(idx.size); + +			if (meta_writer_append(im, &idx, sizeof(idx))) { +				free(diridx); +				return -1; +			} + +			if (meta_writer_append(im, +					       diridx->idx_nodes[i].node->name, +					       le32toh(idx.size) + 1)) { +				free(diridx); +				return -1; +			} +		} + +		free(diridx); +		break; +	} +	default: +		assert(0); +	} +	return 0; +out_file_blocks: +	for (i = 0; i < fi->size / fs->block_size; ++i) { +		bs = htole32(fi->blocksizes[i]); + +		if (meta_writer_append(im, &bs, sizeof(bs))) +			return -1; +	} +	return 0; +} | 
