summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h8
-rw-r--r--lib/Makemodule.am2
-rw-r--r--lib/fstree/fstree.c1
-rw-r--r--lib/fstree/gen_inode_table.c67
-rw-r--r--mkfs/meta.c49
-rw-r--r--mkfs/mkfs.c5
-rw-r--r--mkfs/mkfs.h1
7 files changed, 88 insertions, 45 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 3c9e2af..284792b 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -130,7 +130,6 @@ struct tree_node_t {
Generated on the fly when writing inodes. */
uint64_t inode_ref;
- /* Inode number. Generated on the fly when writing inodes. */
uint32_t inode_num;
/* Type specific data. Pointers are into payload area blow. */
@@ -151,12 +150,16 @@ struct fstree_t {
uint32_t default_mode;
uint32_t default_mtime;
size_t block_size;
+ size_t inode_tbl_size;
str_table_t xattr_keys;
str_table_t xattr_values;
tree_node_t *root;
tree_xattr_t *xattr;
+
+ /* linear array of tree nodes. inode number is array index */
+ tree_node_t **inode_table;
};
/*
@@ -248,4 +251,7 @@ void fstree_sort(fstree_t *fs);
Returns 0 on success. Internally prints errors to stderr. */
int fstree_relabel_selinux(fstree_t *fs, const char *filename);
+/* Returns 0 on success. Prints to stderr on failure */
+int fstree_gen_inode_table(fstree_t *fs);
+
#endif /* FSTREE_H */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 0120347..536cad0 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -1,6 +1,6 @@
libfstree_a_SOURCES = lib/fstree/fstree.c lib/fstree/fstree_from_file.c
libfstree_a_SOURCES += lib/fstree/fstree_sort.c lib/fstree/fstree_from_dir.c
-libfstree_a_SOURCES += include/fstree.h
+libfstree_a_SOURCES += lib/fstree/gen_inode_table.c include/fstree.h
libfstree_a_CFLAGS = $(AM_CFLAGS)
libfstree_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/lib/fstree/fstree.c b/lib/fstree/fstree.c
index 0c3f13d..56ca528 100644
--- a/lib/fstree/fstree.c
+++ b/lib/fstree/fstree.c
@@ -352,5 +352,6 @@ void fstree_cleanup(fstree_t *fs)
str_table_cleanup(&fs->xattr_keys);
str_table_cleanup(&fs->xattr_values);
free_recursive(fs->root);
+ free(fs->inode_table);
memset(fs, 0, sizeof(*fs));
}
diff --git a/lib/fstree/gen_inode_table.c b/lib/fstree/gen_inode_table.c
new file mode 100644
index 0000000..2782c6d
--- /dev/null
+++ b/lib/fstree/gen_inode_table.c
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "fstree.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+static size_t count_nodes(tree_node_t *root)
+{
+ tree_node_t *n = root->data.dir->children;
+ size_t count = 1;
+
+ while (n != NULL) {
+ if (S_ISDIR(n->mode)) {
+ count += count_nodes(n);
+ } else {
+ ++count;
+ }
+ n = n->next;
+ }
+
+ return count;
+}
+
+static void map_child_nodes(fstree_t *fs, tree_node_t *root, size_t *counter)
+{
+ bool has_subdirs = false;
+ tree_node_t *it;
+
+ for (it = root->data.dir->children; it != NULL; it = it->next) {
+ if (S_ISDIR(it->mode)) {
+ has_subdirs = true;
+ break;
+ }
+ }
+
+ if (has_subdirs) {
+ for (it = root->data.dir->children; it != NULL; it = it->next) {
+ if (S_ISDIR(it->mode))
+ map_child_nodes(fs, it, counter);
+ }
+ }
+
+ for (it = root->data.dir->children; it != NULL; it = it->next) {
+ it->inode_num = *counter;
+ *counter += 1;
+
+ fs->inode_table[it->inode_num] = it;
+ }
+}
+
+int fstree_gen_inode_table(fstree_t *fs)
+{
+ size_t inum = 2;
+
+ fs->inode_tbl_size = count_nodes(fs->root) + 2;
+ fs->inode_table = calloc(sizeof(tree_node_t *), fs->inode_tbl_size);
+
+ if (fs->inode_table == NULL) {
+ perror("allocating inode table");
+ return -1;
+ }
+
+ map_child_nodes(fs, fs->root, &inum);
+ fs->root->inode_num = inum;
+ fs->inode_table[inum] = fs->root;
+ return 0;
+}
diff --git a/mkfs/meta.c b/mkfs/meta.c
index 1510524..9c305b1 100644
--- a/mkfs/meta.c
+++ b/mkfs/meta.c
@@ -64,9 +64,6 @@ static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,
meta_writer_get_position(im, &block, &offset);
node->inode_ref = (block << 16) | offset;
- node->inode_num = info->inode_counter++;
-
- info->super.inode_count += 1;
type = get_type(node);
@@ -293,44 +290,13 @@ out_file_blocks:
return 0;
}
-static int write_child_inodes(sqfs_info_t *info, meta_writer_t *im,
- meta_writer_t *dm, tree_node_t *root)
-{
- bool has_subdirs = false;
- tree_node_t *it;
-
- for (it = root->data.dir->children; it != NULL; it = it->next) {
- if (S_ISDIR(it->mode)) {
- has_subdirs = true;
- break;
- }
- }
-
- if (has_subdirs) {
- for (it = root->data.dir->children; it != NULL; it = it->next) {
- if (!S_ISDIR(it->mode))
- continue;
-
- if (write_child_inodes(info, im, dm, it))
- return -1;
- }
- }
-
- for (it = root->data.dir->children; it != NULL; it = it->next) {
- if (write_inode(info, im, dm, it))
- return -1;
- }
-
- return 0;
-}
-
int sqfs_write_inodes(sqfs_info_t *info)
{
meta_writer_t *im, *dm;
uint8_t buffer[1024];
uint32_t offset;
uint64_t block;
- size_t diff;
+ size_t i, diff;
ssize_t ret;
FILE *tmp;
int tmpfd;
@@ -351,13 +317,12 @@ int sqfs_write_inodes(sqfs_info_t *info)
if (dm == NULL)
goto fail_im;
- info->inode_counter = 2;
-
- if (write_child_inodes(info, im, dm, info->fs.root))
- goto fail;
-
- if (write_inode(info, im, dm, info->fs.root))
- goto fail;
+ 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;
+ }
+ }
if (meta_writer_flush(im))
goto fail;
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index a6f19f1..405d6fd 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -89,6 +89,11 @@ int main(int argc, char **argv)
fstree_sort(&info.fs);
+ if (fstree_gen_inode_table(&info.fs))
+ goto out_fstree;
+
+ info.super.inode_count = info.fs.inode_tbl_size - 2;
+
info.cmp = compressor_create(info.super.compression_id, true,
info.super.block_size,
info.opt.comp_extra);
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index 15d349e..e3e3c5d 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -65,7 +65,6 @@ typedef struct {
size_t frag_offset;
id_table_t idtbl;
- size_t inode_counter;
compressor_t *cmp;
} sqfs_info_t;