summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mkfs/Makemodule.am1
-rw-r--r--mkfs/meta.c140
-rw-r--r--mkfs/mkfs.h15
-rw-r--r--mkfs/write_dir.c123
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;
+}