diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2022-04-09 23:20:09 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2022-04-09 23:26:13 +0200 |
commit | 020698f3a92195eb371e806a0b3ed0649565046f (patch) | |
tree | ce27b06f5c30f8cd68879083bbf4dabdb9caf12b /lib/sqfs/dir_reader/dcache.c | |
parent | 94c3fdc66b9aa8130b20a644f399fc021d0a823c (diff) |
Add support for '.' and '..' entries in sqfs_dir_reader_t
Two flags are added to the dir reader API, one for the create function
that the dir reader should report those entries and one to the open
function to suppress that if it was enabled.
To implement the feature, a mapping of visited directory inodes is
maintained internally, that mapps inode numbers to inode references.
When opening a directory, state is maintained to generate the fake
entries for '.' and '..'. Since all the other functions are based on
the open/read/rewind API, no alterations need to be made. The tree
scan function is modified, to use the suppress flag, so it does not
accidentally catch those entries.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/dir_reader/dcache.c')
-rw-r--r-- | lib/sqfs/dir_reader/dcache.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/sqfs/dir_reader/dcache.c b/lib/sqfs/dir_reader/dcache.c new file mode 100644 index 0000000..47fbf73 --- /dev/null +++ b/lib/sqfs/dir_reader/dcache.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * dcache.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#define SQFS_BUILDING_DLL +#include "internal.h" + +static int dcache_key_compare(const void *ctx, const void *l, const void *r) +{ + sqfs_u32 lhs = *((const sqfs_u32 *)l), rhs = *((const sqfs_u32 *)r); + (void)ctx; + + return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0); +} + +int sqfs_dir_reader_dcache_init(sqfs_dir_reader_t *rd, sqfs_u32 flags) +{ + if (!(flags & SQFS_DIR_READER_DOT_ENTRIES)) + return 0; + + return rbtree_init(&rd->dcache, sizeof(sqfs_u32), sizeof(sqfs_u64), + dcache_key_compare); +} + +int sqfs_dir_reader_dcache_init_copy(sqfs_dir_reader_t *copy, + const sqfs_dir_reader_t *rd) +{ + if (!(rd->flags & SQFS_DIR_READER_DOT_ENTRIES)) + return 0; + + return rbtree_copy(&rd->dcache, ©->dcache); +} + +void sqfs_dir_reader_dcache_cleanup(sqfs_dir_reader_t *rd) +{ + if (!(rd->flags & SQFS_DIR_READER_DOT_ENTRIES)) + return; + + rbtree_cleanup(&rd->dcache); +} + +int sqfs_dir_reader_dcache_add(sqfs_dir_reader_t *rd, + sqfs_u32 inode, sqfs_u64 ref) +{ + rbtree_node_t *node; + + if (!(rd->flags & SQFS_DIR_READER_DOT_ENTRIES)) + return 0; + + node = rbtree_lookup(&rd->dcache, &inode); + if (node != NULL) + return 0; + + return rbtree_insert(&rd->dcache, &inode, &ref); +} + +int sqfs_dir_reader_dcache_find(sqfs_dir_reader_t *rd, + sqfs_u32 inode, sqfs_u64 *ref) +{ + rbtree_node_t *node; + + if (!(rd->flags & SQFS_DIR_READER_DOT_ENTRIES)) + return SQFS_ERROR_NO_ENTRY; + + node = rbtree_lookup(&rd->dcache, &inode); + if (node == NULL) + return SQFS_ERROR_NO_ENTRY; + + *ref = *((sqfs_u64 *)rbtree_node_value(node)); + return 0; +} |