diff options
Diffstat (limited to 'mkfs')
| -rw-r--r-- | mkfs/Makemodule.am | 1 | ||||
| -rw-r--r-- | mkfs/meta.c | 140 | ||||
| -rw-r--r-- | mkfs/mkfs.h | 15 | ||||
| -rw-r--r-- | mkfs/write_dir.c | 123 | 
4 files changed, 154 insertions, 125 deletions
| diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index 31340d1..8691fd7 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -1,5 +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_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a  gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/mkfs/meta.c b/mkfs/meta.c index 8f344ef..1510524 100644 --- a/mkfs/meta.c +++ b/mkfs/meta.c @@ -6,56 +6,26 @@  #include <assert.h>  #include <endian.h> -typedef struct { -	tree_node_t *node; -	uint32_t block; -	uint32_t offset; -} idx_ref_t; - -typedef struct { -	size_t num_nodes; -	size_t max_nodes; -	idx_ref_t idx_nodes[]; -} dir_index_t; - -static int get_type(mode_t mode) +static int get_type(tree_node_t *node)  { -	switch (mode & S_IFMT) { -	case S_IFSOCK: return SQFS_INODE_SOCKET; -	case S_IFIFO:  return SQFS_INODE_FIFO; -	case S_IFLNK:  return SQFS_INODE_SLINK; -	case S_IFBLK:  return SQFS_INODE_BDEV; -	case S_IFCHR:  return SQFS_INODE_CDEV; -	case S_IFDIR:  return SQFS_INODE_DIR; -	case S_IFREG:  return SQFS_INODE_FILE; +	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);  	} -} -static int dir_index_grow(dir_index_t **index) -{ -	size_t size = sizeof(dir_index_t) + sizeof(idx_ref_t) * 10; -	void *new; - -	if (*index == NULL) { -		new = calloc(1, size); -	} else { -		if ((*index)->num_nodes < (*index)->max_nodes) -			return 0; - -		size += sizeof(idx_ref_t) * (*index)->num_nodes; -		new = realloc(*index, size); -	} - -	if (new == NULL) { -		perror("creating directory index"); -		return -1; -	} +	if (node->xattr != NULL) +		type = SQFS_INODE_EXT_TYPE(type); -	*index = new; -	(*index)->max_nodes += 10; -	return 0; +	return type;  }  static size_t hard_link_count(tree_node_t *n) @@ -74,83 +44,6 @@ static size_t hard_link_count(tree_node_t *n)  	return 1;  } -static int write_dir(meta_writer_t *dm, dir_info_t *dir, dir_index_t **index) -{ -	size_t i, size, count; -	sqfs_dir_header_t hdr; -	sqfs_dir_entry_t ent; -	tree_node_t *c, *d; -	uint32_t offset; -	uint64_t block; - -	c = dir->children; -	dir->size = 0; - -	meta_writer_get_position(dm, &dir->start_block, &dir->block_offset); - -	while (c != NULL) { -		meta_writer_get_position(dm, &block, &offset); - -		count = 0; -		size = (offset + sizeof(hdr)) % SQFS_META_BLOCK_SIZE; - -		for (d = c; d != NULL; d = d->next) { -			if ((d->inode_ref >> 16) != (c->inode_ref >> 16)) -				break; - -			/* XXX: difference is actually signed */ -			if ((d->inode_num - c->inode_num) > 0x7FFF) -				break; - -			size += sizeof(ent) + strlen(c->name); - -			if (count > 0 && size > SQFS_META_BLOCK_SIZE) -				break; - -			count += 1; -		} - -		if (count > SQFS_MAX_DIR_ENT) -			count = SQFS_MAX_DIR_ENT; - -		if (dir_index_grow(index)) -			return -1; - -		meta_writer_get_position(dm, &block, &offset); - -		i = (*index)->num_nodes++; -		(*index)->idx_nodes[i].node = c; -		(*index)->idx_nodes[i].block = block; -		(*index)->idx_nodes[i].offset = offset; - -		hdr.count = htole32(count - 1); -		hdr.start_block = htole32(c->inode_ref >> 16); -		hdr.inode_number = htole32(c->inode_num); -		dir->size += sizeof(hdr); - -		if (meta_writer_append(dm, &hdr, sizeof(hdr))) -			return -1; - -		d = c; - -		for (i = 0; i < count; ++i) { -			ent.offset = htole16(c->inode_ref & 0x0000FFFF); -			ent.inode_number = htole16(c->inode_num - d->inode_num); -			ent.type = htole16(get_type(c->mode)); -			ent.size = htole16(strlen(c->name) - 1); -			dir->size += sizeof(ent) + strlen(c->name); - -			if (meta_writer_append(dm, &ent, sizeof(ent))) -				return -1; -			if (meta_writer_append(dm, c->name, strlen(c->name))) -				return -1; - -			c = c->next; -		} -	} -	return 0; -} -  static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,  		       tree_node_t *node)  { @@ -175,10 +68,7 @@ static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,  	info->super.inode_count += 1; -	type = get_type(node->mode); - -	if (node->xattr != NULL) -		type = SQFS_INODE_EXT_TYPE(type); +	type = get_type(node);  	if (S_ISDIR(node->mode)) {  		di = node->data.dir; diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index c73b74e..15d349e 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -2,6 +2,7 @@  #ifndef MKFS_H  #define MKFS_H +#include "meta_writer.h"  #include "squashfs.h"  #include "compress.h"  #include "id_table.h" @@ -18,6 +19,18 @@  #include <errno.h>  typedef struct { +	tree_node_t *node; +	uint32_t block; +	uint32_t offset; +} idx_ref_t; + +typedef struct { +	size_t num_nodes; +	size_t max_nodes; +	idx_ref_t idx_nodes[]; +} dir_index_t; + +typedef struct {  	unsigned int def_uid;  	unsigned int def_gid;  	unsigned int def_mode; @@ -65,4 +78,6 @@ int sqfs_write_inodes(sqfs_info_t *info);  int write_xattr(sqfs_info_t *info); +int write_dir(meta_writer_t *dm, dir_info_t *dir, dir_index_t **index); +  #endif /* MKFS_H */ diff --git a/mkfs/write_dir.c b/mkfs/write_dir.c new file mode 100644 index 0000000..c8afb9b --- /dev/null +++ b/mkfs/write_dir.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "mkfs.h" +#include "util.h" + +#include <assert.h> +#include <endian.h> + +static int get_type(mode_t mode) +{ +	switch (mode & S_IFMT) { +	case S_IFSOCK: return SQFS_INODE_SOCKET; +	case S_IFIFO:  return SQFS_INODE_FIFO; +	case S_IFLNK:  return SQFS_INODE_SLINK; +	case S_IFBLK:  return SQFS_INODE_BDEV; +	case S_IFCHR:  return SQFS_INODE_CDEV; +	case S_IFDIR:  return SQFS_INODE_DIR; +	case S_IFREG:  return SQFS_INODE_FILE; +	default: +		assert(0); +	} +} + +static int dir_index_grow(dir_index_t **index) +{ +	size_t size = sizeof(dir_index_t) + sizeof(idx_ref_t) * 10; +	void *new; + +	if (*index == NULL) { +		new = calloc(1, size); +	} else { +		if ((*index)->num_nodes < (*index)->max_nodes) +			return 0; + +		size += sizeof(idx_ref_t) * (*index)->num_nodes; +		new = realloc(*index, size); +	} + +	if (new == NULL) { +		perror("creating directory index"); +		return -1; +	} + +	*index = new; +	(*index)->max_nodes += 10; +	return 0; +} + +int write_dir(meta_writer_t *dm, dir_info_t *dir, dir_index_t **index) +{ +	size_t i, size, count; +	sqfs_dir_header_t hdr; +	sqfs_dir_entry_t ent; +	tree_node_t *c, *d; +	uint32_t offset; +	uint64_t block; + +	c = dir->children; +	dir->size = 0; + +	meta_writer_get_position(dm, &dir->start_block, &dir->block_offset); + +	while (c != NULL) { +		meta_writer_get_position(dm, &block, &offset); + +		count = 0; +		size = (offset + sizeof(hdr)) % SQFS_META_BLOCK_SIZE; + +		for (d = c; d != NULL; d = d->next) { +			if ((d->inode_ref >> 16) != (c->inode_ref >> 16)) +				break; + +			/* XXX: difference is actually signed */ +			if ((d->inode_num - c->inode_num) > 0x7FFF) +				break; + +			size += sizeof(ent) + strlen(c->name); + +			if (count > 0 && size > SQFS_META_BLOCK_SIZE) +				break; + +			count += 1; +		} + +		if (count > SQFS_MAX_DIR_ENT) +			count = SQFS_MAX_DIR_ENT; + +		if (dir_index_grow(index)) +			return -1; + +		meta_writer_get_position(dm, &block, &offset); + +		i = (*index)->num_nodes++; +		(*index)->idx_nodes[i].node = c; +		(*index)->idx_nodes[i].block = block; +		(*index)->idx_nodes[i].offset = offset; + +		hdr.count = htole32(count - 1); +		hdr.start_block = htole32(c->inode_ref >> 16); +		hdr.inode_number = htole32(c->inode_num); +		dir->size += sizeof(hdr); + +		if (meta_writer_append(dm, &hdr, sizeof(hdr))) +			return -1; + +		d = c; + +		for (i = 0; i < count; ++i) { +			ent.offset = htole16(c->inode_ref & 0x0000FFFF); +			ent.inode_number = htole16(c->inode_num - d->inode_num); +			ent.type = htole16(get_type(c->mode)); +			ent.size = htole16(strlen(c->name) - 1); +			dir->size += sizeof(ent) + strlen(c->name); + +			if (meta_writer_append(dm, &ent, sizeof(ent))) +				return -1; +			if (meta_writer_append(dm, c->name, strlen(c->name))) +				return -1; + +			c = c->next; +		} +	} +	return 0; +} | 
