aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-16 15:50:46 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-19 18:22:41 +0200
commitab0c4a02ba9d1a836f62a8601699c971b72eec07 (patch)
tree4ceb7a0a5d9c36189a05750da388941c8a223ebb
parent3f4f75777b9b558e0e8c4af4408b094b6d4b1034 (diff)
Add directory reader data structure
This moves a lot of the stuff that is done manually in the tree deserializer to a generic helper in libsquashfs. Due to how the fstree is implemented, as a work around, the inode needs to be temporarily stored in the tree node, but some of the directory details could be removed. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/fstree.h10
-rw-r--r--include/sqfs/dir.h159
-rw-r--r--include/sqfs/error.h4
-rw-r--r--include/sqfs/predef.h1
-rw-r--r--lib/sqfs/Makemodule.am1
-rw-r--r--lib/sqfs/dir_reader.c266
-rw-r--r--lib/sqfshelper/deserialize_fstree.c165
-rw-r--r--lib/sqfshelper/tree_node_from_inode.c4
8 files changed, 499 insertions, 111 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 4c02ce5..880a870 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -16,6 +16,8 @@
#include <stddef.h>
#include <stdio.h>
+#include "sqfs/inode.h"
+
#include "str_table.h"
#define FSTREE_XATTR_KEY_BUCKETS 31
@@ -105,12 +107,6 @@ struct dir_info_t {
directory meta data to disk. */
uint64_t size;
- /* Start block offset, relative to directory table start. */
- uint64_t start_block;
-
- /* Byte offset into the uncompressed meta data block. */
- uint32_t block_offset;
-
/* Set to true for implicitly generated directories. */
bool created_implicitly;
};
@@ -126,6 +122,8 @@ struct tree_node_t {
/* For the root node, this points to an empty string. */
char *name;
+ sqfs_inode_generic_t *inode;
+
/*
A pointer to an extended attribute array or NULL if unused.
diff --git a/include/sqfs/dir.h b/include/sqfs/dir.h
index 18950df..d8603d7 100644
--- a/include/sqfs/dir.h
+++ b/include/sqfs/dir.h
@@ -59,6 +59,29 @@
* writer used for inodes.
*/
+/**
+ * @struct sqfs_dir_reader_t
+ *
+ * @brief Abstracts reading of directory entries
+ *
+ * SquashFS stores directory listings and inode structures seperated from
+ * each other in meta data blocks.
+ *
+ * The sqfs_dir_reader_t abstracts access to the filesystem tree in a SquashFS
+ * through a fairly simple interface. It keeps two meta data readers internally
+ * for reading directory listings and inodes. Externally, it offers a few
+ * simple functions for iterating over the contents of a directory that
+ * completely take care of fetching/decoding headers and sifting through the
+ * multi level hierarchie used for storing them on disk.
+ *
+ * See @ref sqfs_dir_writer_t for an overview on how directory entries are
+ * stored in SquashFS.
+ *
+ * The reader also abstracts easy access to the underlying inodes, allowing
+ * direct access to the inode referred to by a directory entry.
+ */
+
+
#define SQFS_MAX_DIR_ENT 256
/**
@@ -341,6 +364,142 @@ SQFS_API sqfs_inode_generic_t
*sqfs_dir_writer_create_inode(const sqfs_dir_writer_t *writer, size_t hlinks,
uint32_t xattr, uint32_t parent_ino);
+/**
+ * @brief Create a directory reader.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param super A pointer to the super block. Kept internally an used for
+ * resolving table positions.
+ * @param cmp A compressor to use for unpacking meta data blocks.
+ * @param file The input file to read from.
+ *
+ * @return A new directory reader on success, NULL on allocation failure.
+ */
+SQFS_API sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super,
+ sqfs_compressor_t *cmp,
+ sqfs_file_t *file);
+
+/**
+ * @brief Cleanup a directory reader and free all its memory.
+ *
+ * @memberof sqfs_dir_reader_t
+ */
+SQFS_API void sqfs_dir_reader_destroy(sqfs_dir_reader_t *rd);
+
+/**
+ * @brief Navigate a directory reader to the location of a directory
+ * represented by an inode.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * This function seeks to the meta data block containing the directory
+ * listing that the given inode referes to and resets the internal state.
+ * After that, consequtive cals to @ref sqfs_dir_reader_read can be made
+ * to iterate over the directory contents.
+ *
+ * @param rd A pointer to a directory reader.
+ * @param inode An directory or extended directory inode.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
+ const sqfs_inode_generic_t *inode);
+
+/**
+ * @brief Reset a directory reader back to the beginning of the listing.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param rd A pointer to a directory reader.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_rewind(sqfs_dir_reader_t *rd);
+
+/**
+ * @brief Seek through the current directory listing to locate an
+ * entry by name.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param rd A pointer to a directory reader.
+ * @param name The name of the entry to find.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_find(sqfs_dir_reader_t *rd, const char *name);
+
+/**
+ * @brief Read a directory entry and advance the internal position indicator
+ * to the next one.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * Call this function repeatedly to iterate over a directory listing. It
+ * returns a positive number to indicate that it couldn't fetch any more data
+ * because the end of the listing was reached. A negative value indicates an
+ * error.
+ *
+ * After calling this function, you can use @ref sqfs_dir_reader_get_inode to
+ * read the full inode structure that the current entry referes to.
+ *
+ * @param rd A pointer to a directory reader.
+ * @param out Returns a pointer to a directory entry on success that can be
+ * freed with a single free call.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure, a positive
+ * number if the end of the current directory listing has been reached.
+ */
+SQFS_API int sqfs_dir_reader_read(sqfs_dir_reader_t *rd,
+ sqfs_dir_entry_t **out);
+
+/**
+ * @brief Read the inode that the current directory entry points to.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param rd A pointer to a directory reader.
+ * @param out Returns a pointer to a generic inode that can be freed with a
+ * single free call.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd,
+ sqfs_inode_generic_t **inode);
+
+/**
+ * @brief Read the root inode using the location given by the super block.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param rd A pointer to a directory reader.
+ * @param out Returns a pointer to a generic inode that can be freed with a
+ * single free call.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd,
+ sqfs_inode_generic_t **inode);
+
+/**
+ * @brief Find an inode through path traversal from the root node downwards.
+ *
+ * @memberof sqfs_dir_reader_t
+ *
+ * @param rd A pointer to a directory reader.
+ * @param path A path to resolve into an inode. Forward or backward slashes can
+ * be used to seperate path components. Resolving '.' or '..' is
+ * not supported.
+ * @param out Returns a pointer to a generic inode that can be freed with a
+ * single free call.
+ *
+ * @return Zero on success, an @ref E_SQFS_ERROR value on failure.
+ */
+SQFS_API int sqfs_dir_reader_find_by_path(sqfs_dir_reader_t *rd,
+ const char *path,
+ sqfs_inode_generic_t **out);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/sqfs/error.h b/include/sqfs/error.h
index a9a0acf..ddfeadd 100644
--- a/include/sqfs/error.h
+++ b/include/sqfs/error.h
@@ -103,6 +103,10 @@ typedef enum {
* legal range (4k to 1M).
*/
SQFS_ERROR_SUPER_BLOCK_SIZE = -11,
+
+ SQFS_ERROR_NOT_DIR = -12,
+
+ SQFS_ERROR_NO_ENTRY = -13,
} E_SQFS_ERROR;
#endif /* SQFS_ERROR_H */
diff --git a/include/sqfs/predef.h b/include/sqfs/predef.h
index 95d907f..4041a57 100644
--- a/include/sqfs/predef.h
+++ b/include/sqfs/predef.h
@@ -63,6 +63,7 @@ typedef struct sqfs_block_processor_t sqfs_block_processor_t;
typedef struct sqfs_compressor_config_t sqfs_compressor_config_t;
typedef struct sqfs_compressor_t sqfs_compressor_t;
typedef struct sqfs_dir_writer_t sqfs_dir_writer_t;
+typedef struct sqfs_dir_reader_t sqfs_dir_reader_t;
typedef struct sqfs_id_table_t sqfs_id_table_t;
typedef struct sqfs_meta_reader_t sqfs_meta_reader_t;
typedef struct sqfs_meta_writer_t sqfs_meta_writer_t;
diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am
index 7d228a4..807c104 100644
--- a/lib/sqfs/Makemodule.am
+++ b/lib/sqfs/Makemodule.am
@@ -14,6 +14,7 @@ libsquashfs_la_SOURCES += lib/sqfs/read_inode.c lib/sqfs/write_inode.c
libsquashfs_la_SOURCES += lib/sqfs/dir_writer.c lib/sqfs/xattr_reader.c
libsquashfs_la_SOURCES += lib/sqfs/read_table.c lib/sqfs/comp/compressor.c
libsquashfs_la_SOURCES += lib/sqfs/io_stdin.c lib/sqfs/comp/internal.h
+libsquashfs_la_SOURCES += lib/sqfs/dir_reader.c
libsquashfs_la_SOURCES += lib/sqfs/blk_proc/process_block.c lib/sqfs/io.c
libsquashfs_la_SOURCES += lib/sqfs/blk_proc/internal.h
libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/lib/sqfs/dir_reader.c b/lib/sqfs/dir_reader.c
new file mode 100644
index 0000000..d4bfd27
--- /dev/null
+++ b/lib/sqfs/dir_reader.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+/*
+ * fs_reader.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#define SQFS_BUILDING_DLL
+#include "config.h"
+
+#include "sqfs/meta_reader.h"
+#include "sqfs/compress.h"
+#include "sqfs/super.h"
+#include "sqfs/inode.h"
+#include "sqfs/error.h"
+#include "sqfs/dir.h"
+#include "util.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+struct sqfs_dir_reader_t {
+ sqfs_meta_reader_t *meta_dir;
+ sqfs_meta_reader_t *meta_inode;
+ const sqfs_super_t *super;
+
+ sqfs_dir_header_t hdr;
+ uint64_t dir_block_start;
+ size_t entries;
+ size_t size;
+
+ size_t start_size;
+ uint16_t dir_offset;
+ uint16_t inode_offset;
+};
+
+sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super,
+ sqfs_compressor_t *cmp,
+ sqfs_file_t *file)
+{
+ sqfs_dir_reader_t *rd = calloc(1, sizeof(*rd));
+ uint64_t start, limit;
+
+ if (rd == NULL)
+ return NULL;
+
+ start = super->inode_table_start;
+ limit = super->directory_table_start;
+
+ rd->meta_inode = sqfs_meta_reader_create(file, cmp, start, limit);
+
+ if (rd->meta_inode == NULL) {
+ free(rd);
+ return NULL;
+ }
+
+ start = super->directory_table_start;
+ limit = super->id_table_start;
+
+ if (super->fragment_table_start < limit)
+ limit = super->fragment_table_start;
+
+ if (super->export_table_start < limit)
+ limit = super->export_table_start;
+
+ rd->meta_dir = sqfs_meta_reader_create(file, cmp, start, limit);
+
+ if (rd->meta_dir == NULL) {
+ sqfs_meta_reader_destroy(rd->meta_inode);
+ free(rd);
+ return NULL;
+ }
+
+ rd->super = super;
+ return rd;
+}
+
+void sqfs_dir_reader_destroy(sqfs_dir_reader_t *rd)
+{
+ sqfs_meta_reader_destroy(rd->meta_inode);
+ sqfs_meta_reader_destroy(rd->meta_dir);
+ free(rd);
+}
+
+int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
+ const sqfs_inode_generic_t *inode)
+{
+ uint64_t block_start;
+ size_t size, offset;
+
+ if (inode->base.type == SQFS_INODE_DIR) {
+ size = inode->data.dir.size;
+ offset = inode->data.dir.offset;
+ block_start = inode->data.dir.start_block;
+ } else if (inode->base.type == SQFS_INODE_EXT_DIR) {
+ size = inode->data.dir_ext.size;
+ offset = inode->data.dir_ext.offset;
+ block_start = inode->data.dir_ext.start_block;
+ } else {
+ return SQFS_ERROR_NOT_DIR;
+ }
+
+ memset(&rd->hdr, 0, sizeof(rd->hdr));
+ rd->size = size;
+ rd->entries = 0;
+
+ if (rd->size <= sizeof(rd->hdr))
+ return 0;
+
+ block_start += rd->super->directory_table_start;
+
+ rd->dir_block_start = block_start;
+ rd->dir_offset = offset;
+ rd->start_size = size;
+
+ return sqfs_meta_reader_seek(rd->meta_dir, block_start, offset);
+}
+
+int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_entry_t **out)
+{
+ sqfs_dir_entry_t *ent;
+ size_t count;
+ int err;
+
+ if (!rd->entries) {
+ if (rd->size < sizeof(rd->hdr))
+ return 1;
+
+ err = sqfs_meta_reader_read_dir_header(rd->meta_dir, &rd->hdr);
+ if (err)
+ return err;
+
+ rd->size -= sizeof(rd->hdr);
+ rd->entries = rd->hdr.count + 1;
+ }
+
+ err = sqfs_meta_reader_read_dir_ent(rd->meta_dir, &ent);
+ if (err)
+ return err;
+
+ count = sizeof(*ent) + strlen((const char *)ent->name);
+
+ if (count > rd->size) {
+ rd->size = 0;
+ rd->entries = 0;
+ } else {
+ rd->size -= count;
+ rd->entries -= 1;
+ }
+
+ rd->inode_offset = ent->offset;
+ *out = ent;
+ return 0;
+}
+
+int sqfs_dir_reader_rewind(sqfs_dir_reader_t *rd)
+{
+ memset(&rd->hdr, 0, sizeof(rd->hdr));
+ rd->size = rd->start_size;
+ rd->entries = 0;
+
+ return sqfs_meta_reader_seek(rd->meta_dir, rd->dir_block_start,
+ rd->dir_offset);
+}
+
+int sqfs_dir_reader_find(sqfs_dir_reader_t *rd, const char *name)
+{
+ sqfs_dir_entry_t *ent;
+ int ret;
+
+ if (rd->size != rd->start_size) {
+ ret = sqfs_dir_reader_rewind(rd);
+ if (ret)
+ return ret;
+ }
+
+ do {
+ ret = sqfs_dir_reader_read(rd, &ent);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return SQFS_ERROR_NO_ENTRY;
+
+ ret = strcmp((const char *)ent->name, name);
+ free(ent);
+ } while (ret < 0);
+
+ return ret == 0 ? 0 : SQFS_ERROR_NO_ENTRY;
+}
+
+int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd,
+ sqfs_inode_generic_t **inode)
+{
+ uint64_t block_start;
+
+ block_start = rd->hdr.start_block;
+
+ return sqfs_meta_reader_read_inode(rd->meta_inode, rd->super,
+ block_start, rd->inode_offset,
+ inode);
+}
+
+int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd,
+ sqfs_inode_generic_t **inode)
+{
+ uint64_t block_start = rd->super->root_inode_ref >> 16;
+ uint16_t offset = rd->super->root_inode_ref & 0xFFFF;
+
+ return sqfs_meta_reader_read_inode(rd->meta_inode, rd->super,
+ block_start, offset, inode);
+}
+
+int sqfs_dir_reader_find_by_path(sqfs_dir_reader_t *rd, const char *path,
+ sqfs_inode_generic_t **out)
+{
+ sqfs_inode_generic_t *inode;
+ sqfs_dir_entry_t *ent;
+ const char *ptr;
+ int ret;
+
+ ret = sqfs_dir_reader_get_root_inode(rd, &inode);
+ if (ret)
+ return ret;
+
+ while (*path != '\0') {
+ if (*path == '/' || *path == '\\') {
+ while (*path == '/' || *path == '\\')
+ ++path;
+ continue;
+ }
+
+ ret = sqfs_dir_reader_open_dir(rd, inode);
+ free(inode);
+ if (ret)
+ return ret;
+
+ ptr = strchr(path, '/');
+ if (ptr == NULL)
+ ptr = strchrnul(path, '\\');
+
+ do {
+ ret = sqfs_dir_reader_read(rd, &ent);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0) {
+ ret = strncmp((const char *)ent->name,
+ path, ptr - path);
+ if (ret == 0)
+ ret = ent->name[ptr - path];
+ free(ent);
+ }
+ } while (ret < 0);
+
+ if (ret > 0)
+ return SQFS_ERROR_NO_ENTRY;
+
+ ret = sqfs_dir_reader_get_inode(rd, &inode);
+ if (ret)
+ return ret;
+
+ path = ptr;
+ }
+
+ *out = inode;
+ return 0;
+}
diff --git a/lib/sqfshelper/deserialize_fstree.c b/lib/sqfshelper/deserialize_fstree.c
index ef000d4..e0f53e7 100644
--- a/lib/sqfshelper/deserialize_fstree.c
+++ b/lib/sqfshelper/deserialize_fstree.c
@@ -93,102 +93,70 @@ fail:
return false;
}
-static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr,
- tree_node_t *root, sqfs_super_t *super,
- sqfs_id_table_t *idtbl,
+static int fill_dir(sqfs_dir_reader_t *dr,
+ tree_node_t *root, sqfs_id_table_t *idtbl,
fstree_t *fs, sqfs_xattr_reader_t *xr, int flags)
{
sqfs_inode_generic_t *inode;
- sqfs_dir_header_t hdr;
sqfs_dir_entry_t *ent;
tree_node_t *n, *prev;
- uint64_t block_start;
- size_t size, diff;
- uint32_t i;
int err;
- size = root->data.dir->size;
- if (size <= sizeof(hdr))
- return 0;
-
- block_start = root->data.dir->start_block;
- block_start += super->directory_table_start;
-
- if (sqfs_meta_reader_seek(dr, block_start,
- root->data.dir->block_offset)) {
- return -1;
- }
-
- while (size > sizeof(hdr)) {
- if (sqfs_meta_reader_read_dir_header(dr, &hdr))
+ for (;;) {
+ err = sqfs_dir_reader_read(dr, &ent);
+ if (err > 0)
+ break;
+ if (err < 0)
return -1;
- size -= sizeof(hdr);
-
- for (i = 0; i <= hdr.count && size > sizeof(*ent); ++i) {
- if (sqfs_meta_reader_read_dir_ent(dr, &ent))
- return -1;
-
- diff = sizeof(*ent) + strlen((char *)ent->name);
- if (diff > size) {
- free(ent);
- break;
- }
- size -= diff;
-
- if (should_skip(ent->type, flags)) {
- free(ent);
- continue;
- }
+ if (should_skip(ent->type, flags)) {
+ free(ent);
+ continue;
+ }
- if (!is_name_sane((const char *)ent->name)) {
- free(ent);
- continue;
- }
+ if (!is_name_sane((const char *)ent->name)) {
+ free(ent);
+ continue;
+ }
- err = sqfs_meta_reader_read_inode(ir, super,
- hdr.start_block,
- ent->offset, &inode);
- if (err) {
- free(ent);
- return err;
- }
+ err = sqfs_dir_reader_get_inode(dr, &inode);
+ if (err) {
+ free(ent);
+ return err;
+ }
- n = tree_node_from_inode(inode, idtbl,
- (char *)ent->name);
+ n = tree_node_from_inode(inode, idtbl, (char *)ent->name);
+ if (n == NULL) {
+ free(ent);
+ free(inode);
+ return -1;
+ }
- if (n == NULL) {
- free(ent);
- free(inode);
- return -1;
- }
+ if (node_would_be_own_parent(root, n)) {
+ fputs("WARNING: Found a directory that "
+ "contains itself, skipping loop back "
+ "reference!\n", stderr);
+ free(n);
+ free(ent);
+ free(inode);
+ continue;
+ }
- if (node_would_be_own_parent(root, n)) {
- fputs("WARNING: Found a directory that "
- "contains itself, skipping loop back "
- "reference!\n", stderr);
+ if (flags & RDTREE_READ_XATTR) {
+ if (restore_xattr(xr, fs, n, inode)) {
free(n);
free(ent);
free(inode);
- continue;
+ return -1;
}
+ }
- if (flags & RDTREE_READ_XATTR) {
- if (restore_xattr(xr, fs, n, inode)) {
- free(n);
- free(ent);
- free(inode);
- return -1;
- }
- }
+ free(ent);
- free(ent);
- free(inode);
-
- n->parent = root;
- n->next = root->data.dir->children;
- root->data.dir->children = n;
- }
+ n->inode = inode;
+ n->parent = root;
+ n->next = root->data.dir->children;
+ root->data.dir->children = n;
}
n = root->data.dir->children;
@@ -196,11 +164,16 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr,
while (n != NULL) {
if (S_ISDIR(n->mode)) {
- if (fill_dir(ir, dr, n, super, idtbl, fs, xr, flags))
+ err = sqfs_dir_reader_open_dir(dr, n->inode);
+ if (err)
+ return -1;
+
+ if (fill_dir(dr, n, idtbl, fs, xr, flags))
return -1;
if (n->data.dir->children == NULL &&
(flags & RDTREE_NO_EMPTY)) {
+ free(n->inode);
if (prev == NULL) {
root->data.dir->children = n->next;
free(n);
@@ -214,6 +187,9 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr,
}
}
+ free(n->inode);
+ n->inode = NULL;
+
prev = n;
n = n->next;
}
@@ -224,29 +200,15 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr,
int deserialize_fstree(fstree_t *out, sqfs_super_t *super,
sqfs_compressor_t *cmp, sqfs_file_t *file, int flags)
{
- uint64_t block_start, limit;
- sqfs_meta_reader_t *ir, *dr;
sqfs_inode_generic_t *root;
sqfs_xattr_reader_t *xr;
sqfs_id_table_t *idtbl;
+ sqfs_dir_reader_t *dr;
int status = -1;
- size_t offset;
-
- ir = sqfs_meta_reader_create(file, cmp, super->inode_table_start,
- super->directory_table_start);
- if (ir == NULL)
- return -1;
-
- limit = super->id_table_start;
- if (super->export_table_start < limit)
- limit = super->export_table_start;
- if (super->fragment_table_start < limit)
- limit = super->fragment_table_start;
- dr = sqfs_meta_reader_create(file, cmp, super->directory_table_start,
- limit);
+ dr = sqfs_dir_reader_create(super, cmp, file);
if (dr == NULL)
- goto out_ir;
+ return -1;
idtbl = sqfs_id_table_create();
if (idtbl == NULL)
@@ -262,9 +224,7 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super,
if (sqfs_xattr_reader_load_locations(xr))
goto out_xr;
- block_start = super->root_inode_ref >> 16;
- offset = super->root_inode_ref & 0xFFFF;
- if (sqfs_meta_reader_read_inode(ir, super, block_start, offset, &root))
+ if (sqfs_dir_reader_get_root_inode(dr, &root))
goto out_xr;
if (root->base.type != SQFS_INODE_DIR &&
@@ -308,9 +268,14 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super,
}
}
+ if (sqfs_dir_reader_open_dir(dr, root)) {
+ free(root);
+ goto fail_fs;
+ }
+
free(root);
- if (fill_dir(ir, dr, out->root, super, idtbl, out, xr, flags))
+ if (fill_dir(dr, out->root, idtbl, out, xr, flags))
goto fail_fs;
tree_node_sort_recursive(out->root);
@@ -321,9 +286,7 @@ out_xr:
out_id:
sqfs_id_table_destroy(idtbl);
out_dr:
- sqfs_meta_reader_destroy(dr);
-out_ir:
- sqfs_meta_reader_destroy(ir);
+ sqfs_dir_reader_destroy(dr);
return status;
fail_fs:
fstree_cleanup(out);
diff --git a/lib/sqfshelper/tree_node_from_inode.c b/lib/sqfshelper/tree_node_from_inode.c
index f5b643c..3ada722 100644
--- a/lib/sqfshelper/tree_node_from_inode.c
+++ b/lib/sqfshelper/tree_node_from_inode.c
@@ -82,16 +82,12 @@ tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode,
out->name += sizeof(dir_info_t);
out->data.dir->size = inode->data.dir.size;
- out->data.dir->start_block = inode->data.dir.start_block;
- out->data.dir->block_offset = inode->data.dir.offset;
break;
case SQFS_INODE_EXT_DIR:
out->data.dir = (dir_info_t *)out->payload;
out->name += sizeof(dir_info_t);
out->data.dir->size = inode->data.dir_ext.size;
- out->data.dir->start_block = inode->data.dir_ext.start_block;
- out->data.dir->block_offset = inode->data.dir_ext.offset;
break;
case SQFS_INODE_FILE:
out->data.file = (file_info_t *)out->payload;