From f0479f3acd90a46f8354277360c96763fa74ef65 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 15 Sep 2023 16:29:10 +0200 Subject: libsqfs: dir reader: encapsulate internal state in a separate object Signed-off-by: David Oberhollenzer --- include/sqfs/dir_reader.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++ include/sqfs/predef.h | 1 + lib/sqfs/src/dir_reader.c | 52 +++++++++++++++++++++-------------------------- 3 files changed, 76 insertions(+), 29 deletions(-) diff --git a/include/sqfs/dir_reader.h b/include/sqfs/dir_reader.h index abd49bd..eb90b7a 100644 --- a/include/sqfs/dir_reader.h +++ b/include/sqfs/dir_reader.h @@ -21,6 +21,7 @@ #define SQFS_DIR_READER_H #include "sqfs/predef.h" +#include "sqfs/meta_reader.h" /** * @file dir_reader.h @@ -97,6 +98,57 @@ typedef enum { SQFS_DIR_OPEN_ALL_FLAGS = 0x00000001, } SQFS_DIR_OPEN_FLAGS; +/** + * @brief sqfs_dir_reader_state_t + * + * @extends sqfs_readdir_state_t + * + * A meta data cursor for reading a directory, but with additional data + * for the @ref sqfs_dir_reader_t, e.g. for resolving inodes. + */ +struct sqfs_dir_reader_state_t { + /** + * @brief Base cursor structure for the directory meta data + */ + sqfs_readdir_state_t cursor; + + /** + * @brief An inode reference to the parent inode of the directory + * + * This is only available if the reader was created with + * the @ref SQFS_DIR_READER_DOT_ENTRIES flag and the behavior was + * not disabled when opening the directory. + */ + sqfs_u64 parent_ref; + + /** + * @brief A reference to the inode of the directory itself + * + * This is only available if the reader was created with + * the @ref SQFS_DIR_READER_DOT_ENTRIES flag and the behavior was + * not disabled when opening the directory. + */ + sqfs_u64 cur_ref; + + /** + * @brief A reference to the current entries inode + * + * After a successfull call to @ref sqfs_dir_reader_read, this contains + * a reference to the inode coresponding to the returned entry. + */ + sqfs_u64 ent_ref; + + /** + * @brief An opaque, internal state value + */ + sqfs_u8 state; + + /** + * @brief A backup of `state` to reset the state if requested + */ + sqfs_u8 start_state; +}; + #ifdef __cplusplus extern "C" { #endif diff --git a/include/sqfs/predef.h b/include/sqfs/predef.h index fbc6519..8e7c1b8 100644 --- a/include/sqfs/predef.h +++ b/include/sqfs/predef.h @@ -80,6 +80,7 @@ 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_dir_reader_state_t sqfs_dir_reader_state_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/src/dir_reader.c b/lib/sqfs/src/dir_reader.c index c44198e..ce93795 100644 --- a/lib/sqfs/src/dir_reader.c +++ b/lib/sqfs/src/dir_reader.c @@ -33,16 +33,11 @@ struct sqfs_dir_reader_t { sqfs_meta_reader_t *meta_inode; sqfs_super_t super; - sqfs_readdir_state_t it; - sqfs_u32 flags; - int start_state; - int state; - sqfs_u64 parent_ref; - sqfs_u64 cur_ref; - sqfs_u64 ent_ref; rbtree_t dcache; + + sqfs_dir_reader_state_t state; }; static int inode_copy(const sqfs_inode_generic_t *inode, @@ -192,7 +187,6 @@ sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super, rd->super = *super; rd->flags = flags; - rd->state = DIR_STATE_NONE; return rd; fail_mdir: sqfs_drop(rd->meta_inode); @@ -214,7 +208,7 @@ 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->it, &rd->super, inode); + ret = sqfs_readdir_state_init(&rd->state.cursor, &rd->super, inode); if (ret) return ret; @@ -226,21 +220,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->cur_ref)) + if (dcache_find(rd, inode->base.inode_number, &rd->state.cur_ref)) return SQFS_ERROR_NO_ENTRY; - if (rd->cur_ref == rd->super.root_inode_ref) { - rd->parent_ref = rd->cur_ref; - } else if (dcache_find(rd, parent, &rd->parent_ref)) { + 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)) { return SQFS_ERROR_NO_ENTRY; } - rd->state = DIR_STATE_OPENED; + rd->state.state = DIR_STATE_OPENED; } else { - rd->state = DIR_STATE_ENTRIES; + rd->state.state = DIR_STATE_ENTRIES; } - rd->start_state = rd->state; + rd->state.start_state = rd->state.state; return 0; } @@ -266,19 +260,19 @@ int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_node_t **out) { int err; - switch (rd->state) { + switch (rd->state.state) { case DIR_STATE_OPENED: err = mk_dummy_entry(".", out); if (err == 0) { - rd->state = DIR_STATE_DOT; - rd->ent_ref = rd->cur_ref; + rd->state.state = DIR_STATE_DOT; + rd->state.ent_ref = rd->state.cur_ref; } return err; case DIR_STATE_DOT: err = mk_dummy_entry("..", out); if (err == 0) { - rd->state = DIR_STATE_ENTRIES; - rd->ent_ref = rd->parent_ref; + rd->state.state = DIR_STATE_ENTRIES; + rd->state.ent_ref = rd->state.parent_ref; } return err; case DIR_STATE_ENTRIES: @@ -287,17 +281,17 @@ 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->it, - out, NULL, &rd->ent_ref); + return sqfs_meta_reader_readdir(rd->meta_dir, &rd->state.cursor, + out, NULL, &rd->state.ent_ref); } int sqfs_dir_reader_rewind(sqfs_dir_reader_t *rd) { - if (rd->state == DIR_STATE_NONE) + if (rd->state.state == DIR_STATE_NONE) return SQFS_ERROR_SEQUENCE; - sqfs_readdir_state_reset(&rd->it); - rd->state = rd->start_state; + sqfs_readdir_state_reset(&rd->state.cursor); + rd->state.state = rd->state.start_state; return 0; } @@ -307,12 +301,12 @@ int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd, int ret; ret = sqfs_meta_reader_read_inode(rd->meta_inode, &rd->super, - rd->ent_ref >> 16, - rd->ent_ref & 0x0FFFF, inode); + rd->state.ent_ref >> 16, + rd->state.ent_ref & 0x0FFFF, inode); if (ret != 0) return ret; - return dcache_add(rd, *inode, rd->ent_ref); + return dcache_add(rd, *inode, rd->state.ent_ref); } int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd, -- cgit v1.2.3