aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-15 18:02:50 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-15 21:48:47 +0200
commit69ac85c09dac74f9691b2ed340438e9648516c9f (patch)
treecec97b1d112f29460739563096c3740a8f2cf648
parent0b3f650fa4eb0dcce2258c7bb8974a1304468a05 (diff)
libsqfs: externalize the dir reader state
Instead of holding the state internally, move it outside and let the user pass it in. This allows processing multiple directories and going back and forth between them, while also simplifying the dir reader internals. The sqfs_dir_reader_get_inode function can also be made more generic to accept a reference instead of being fully state dependent. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/sqfs/dir_reader.h10
-rw-r--r--lib/common/src/read_tree.c24
-rw-r--r--lib/sqfs/src/dir_reader.c56
3 files changed, 45 insertions, 45 deletions
diff --git a/include/sqfs/dir_reader.h b/include/sqfs/dir_reader.h
index 0f1f231..1c95e30 100644
--- a/include/sqfs/dir_reader.h
+++ b/include/sqfs/dir_reader.h
@@ -204,6 +204,7 @@ SQFS_API sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super,
*/
SQFS_API int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
const sqfs_inode_generic_t *inode,
+ sqfs_dir_reader_state_t *state,
sqfs_u32 flags);
/**
@@ -217,9 +218,6 @@ SQFS_API int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
* 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 @ref sqfs_free call.
@@ -228,20 +226,22 @@ SQFS_API int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
* 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_reader_state_t *state,
sqfs_dir_node_t **out);
/**
- * @brief Read the inode that the current directory entry points to.
+ * @brief Resolve and deserialize an inode using an inode reference
*
* @memberof sqfs_dir_reader_t
*
* @param rd A pointer to a directory reader.
+ * @param ref An inode reference.
* @param out Returns a pointer to a generic inode that can be freed with a
* single @ref sqfs_free call.
*
* @return Zero on success, an @ref SQFS_ERROR value on failure.
*/
-SQFS_API int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd,
+SQFS_API int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd, sqfs_u64 ref,
sqfs_inode_generic_t **inode);
/**
diff --git a/lib/common/src/read_tree.c b/lib/common/src/read_tree.c
index 5d089e5..2879ff4 100644
--- a/lib/common/src/read_tree.c
+++ b/lib/common/src/read_tree.c
@@ -63,6 +63,7 @@ static sqfs_tree_node_t *create_node(sqfs_inode_generic_t *inode,
}
static int fill_dir(sqfs_dir_reader_t *dr, sqfs_tree_node_t *root,
+ sqfs_dir_reader_state_t *state,
unsigned int flags)
{
sqfs_tree_node_t *n, *prev, **tail;
@@ -73,7 +74,7 @@ static int fill_dir(sqfs_dir_reader_t *dr, sqfs_tree_node_t *root,
tail = &root->children;
for (;;) {
- err = sqfs_dir_reader_read(dr, &ent);
+ err = sqfs_dir_reader_read(dr, state, &ent);
if (err > 0)
break;
if (err < 0)
@@ -84,7 +85,7 @@ static int fill_dir(sqfs_dir_reader_t *dr, sqfs_tree_node_t *root,
continue;
}
- err = sqfs_dir_reader_get_inode(dr, &inode);
+ err = sqfs_dir_reader_get_inode(dr, state->ent_ref, &inode);
if (err) {
free(ent);
return err;
@@ -115,13 +116,16 @@ static int fill_dir(sqfs_dir_reader_t *dr, sqfs_tree_node_t *root,
while (n != NULL) {
if (n->inode->base.type == SQFS_INODE_DIR ||
n->inode->base.type == SQFS_INODE_EXT_DIR) {
+ sqfs_dir_reader_state_t nstate;
+
if (!(flags & SQFS_TREE_NO_RECURSE)) {
err = sqfs_dir_reader_open_dir(dr, n->inode,
+ &nstate,
SQFS_DIR_OPEN_NO_DOT_ENTRIES);
if (err)
return err;
- err = fill_dir(dr, n, flags);
+ err = fill_dir(dr, n, &nstate, flags);
if (err)
return err;
}
@@ -192,13 +196,15 @@ int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd,
inode = NULL;
while (path != NULL && *path != '\0') {
+ sqfs_dir_reader_state_t state;
+
if (*path == '/') {
while (*path == '/')
++path;
continue;
}
- ret = sqfs_dir_reader_open_dir(rd, tail->inode,
+ ret = sqfs_dir_reader_open_dir(rd, tail->inode, &state,
SQFS_DIR_OPEN_NO_DOT_ENTRIES);
if (ret)
goto fail;
@@ -206,7 +212,7 @@ int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd,
ptr = strchrnul(path, '/');
for (;;) {
- ret = sqfs_dir_reader_read(rd, &ent);
+ ret = sqfs_dir_reader_read(rd, &state, &ent);
if (ret < 0)
goto fail;
if (ret > 0) {
@@ -221,7 +227,7 @@ int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd,
free(ent);
}
- ret = sqfs_dir_reader_get_inode(rd, &inode);
+ ret = sqfs_dir_reader_get_inode(rd, state.ent_ref, &inode);
if (ret) {
free(ent);
goto fail;
@@ -251,12 +257,14 @@ int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd,
if (tail->inode->base.type == SQFS_INODE_DIR ||
tail->inode->base.type == SQFS_INODE_EXT_DIR) {
- ret = sqfs_dir_reader_open_dir(rd, tail->inode,
+ sqfs_dir_reader_state_t state;
+
+ ret = sqfs_dir_reader_open_dir(rd, tail->inode, &state,
SQFS_DIR_OPEN_NO_DOT_ENTRIES);
if (ret)
goto fail;
- ret = fill_dir(rd, tail, flags);
+ ret = fill_dir(rd, tail, &state, flags);
if (ret)
goto fail;
}
diff --git a/lib/sqfs/src/dir_reader.c b/lib/sqfs/src/dir_reader.c
index c904f35..2b6d0e8 100644
--- a/lib/sqfs/src/dir_reader.c
+++ b/lib/sqfs/src/dir_reader.c
@@ -36,8 +36,6 @@ struct sqfs_dir_reader_t {
sqfs_u32 flags;
rbtree_t dcache;
-
- sqfs_dir_reader_state_t state;
};
static int dcache_key_compare(const void *ctx, const void *l, const void *r)
@@ -189,6 +187,7 @@ fail_dcache:
int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
const sqfs_inode_generic_t *inode,
+ sqfs_dir_reader_state_t *state,
sqfs_u32 flags)
{
sqfs_u32 parent;
@@ -197,7 +196,9 @@ int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
if (flags & (~SQFS_DIR_OPEN_ALL_FLAGS))
return SQFS_ERROR_UNSUPPORTED;
- ret = sqfs_readdir_state_init(&rd->state.cursor, &rd->super, inode);
+ memset(state, 0, sizeof(*state));
+
+ ret = sqfs_readdir_state_init(&state->cursor, &rd->super, inode);
if (ret)
return ret;
@@ -209,21 +210,21 @@ int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd,
parent = inode->data.dir.parent_inode;
}
- if (dcache_find(rd, inode->base.inode_number, &rd->state.cur_ref))
+ if (dcache_find(rd, inode->base.inode_number, &state->cur_ref))
return SQFS_ERROR_NO_ENTRY;
- if (rd->state.cur_ref == rd->super.root_inode_ref) {
- rd->state.parent_ref = rd->state.cur_ref;
- } else if (dcache_find(rd, parent, &rd->state.parent_ref)) {
+ if (state->cur_ref == rd->super.root_inode_ref) {
+ state->parent_ref = state->cur_ref;
+ } else if (dcache_find(rd, parent, &state->parent_ref)) {
return SQFS_ERROR_NO_ENTRY;
}
- rd->state.state = DIR_STATE_OPENED;
+ state->state = DIR_STATE_OPENED;
} else {
- rd->state.state = DIR_STATE_ENTRIES;
+ state->state = DIR_STATE_ENTRIES;
}
- rd->state.start_state = rd->state.state;
+ state->start_state = state->state;
return 0;
}
@@ -245,23 +246,24 @@ static int mk_dummy_entry(const char *str, sqfs_dir_node_t **out)
return 0;
}
-int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_node_t **out)
+int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_reader_state_t *state,
+ sqfs_dir_node_t **out)
{
int err;
- switch (rd->state.state) {
+ switch (state->state) {
case DIR_STATE_OPENED:
err = mk_dummy_entry(".", out);
if (err == 0) {
- rd->state.state = DIR_STATE_DOT;
- rd->state.ent_ref = rd->state.cur_ref;
+ state->state = DIR_STATE_DOT;
+ state->ent_ref = state->cur_ref;
}
return err;
case DIR_STATE_DOT:
err = mk_dummy_entry("..", out);
if (err == 0) {
- rd->state.state = DIR_STATE_ENTRIES;
- rd->state.ent_ref = rd->state.parent_ref;
+ state->state = DIR_STATE_ENTRIES;
+ state->ent_ref = state->parent_ref;
}
return err;
case DIR_STATE_ENTRIES:
@@ -270,35 +272,25 @@ int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_node_t **out)
return SQFS_ERROR_SEQUENCE;
}
- return sqfs_meta_reader_readdir(rd->meta_dir, &rd->state.cursor,
- out, NULL, &rd->state.ent_ref);
+ return sqfs_meta_reader_readdir(rd->meta_dir, &state->cursor,
+ out, NULL, &state->ent_ref);
}
-int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd,
+int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd, sqfs_u64 ref,
sqfs_inode_generic_t **inode)
{
int ret;
ret = sqfs_meta_reader_read_inode(rd->meta_inode, &rd->super,
- rd->state.ent_ref >> 16,
- rd->state.ent_ref & 0x0FFFF, inode);
+ ref >> 16, ref & 0x0FFFF, inode);
if (ret != 0)
return ret;
- return dcache_add(rd, *inode, rd->state.ent_ref);
+ return dcache_add(rd, *inode, ref);
}
int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd,
sqfs_inode_generic_t **inode)
{
- sqfs_u64 block_start = rd->super.root_inode_ref >> 16;
- sqfs_u16 offset = rd->super.root_inode_ref & 0xFFFF;
- int ret;
-
- ret = sqfs_meta_reader_read_inode(rd->meta_inode, &rd->super,
- block_start, offset, inode);
- if (ret != 0)
- return ret;
-
- return dcache_add(rd, *inode, rd->super.root_inode_ref);
+ return sqfs_dir_reader_get_inode(rd, rd->super.root_inode_ref, inode);
}