From cdccc69c62579b0c13b35fad0728079652b8f3c9 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 31 Jan 2023 11:21:30 +0100 Subject: Move library source into src sub-directory Signed-off-by: David Oberhollenzer --- lib/sqfs/src/readdir.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 lib/sqfs/src/readdir.c (limited to 'lib/sqfs/src/readdir.c') diff --git a/lib/sqfs/src/readdir.c b/lib/sqfs/src/readdir.c new file mode 100644 index 0000000..e2dbcd4 --- /dev/null +++ b/lib/sqfs/src/readdir.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * readdir.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#define SQFS_BUILDING_DLL +#include "config.h" + +#include "sqfs/meta_reader.h" +#include "sqfs/error.h" +#include "sqfs/super.h" +#include "sqfs/inode.h" +#include "sqfs/dir.h" +#include "compat.h" + +#include +#include + +int sqfs_meta_reader_read_dir_header(sqfs_meta_reader_t *m, + sqfs_dir_header_t *hdr) +{ + int err = sqfs_meta_reader_read(m, hdr, sizeof(*hdr)); + if (err) + return err; + + hdr->count = le32toh(hdr->count); + hdr->start_block = le32toh(hdr->start_block); + hdr->inode_number = le32toh(hdr->inode_number); + + if (hdr->count > (SQFS_MAX_DIR_ENT - 1)) + return SQFS_ERROR_CORRUPTED; + + return 0; +} + +int sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m, + sqfs_dir_entry_t **result) +{ + sqfs_dir_entry_t ent, *out; + sqfs_u16 *diff_u16; + int err; + + err = sqfs_meta_reader_read(m, &ent, sizeof(ent)); + if (err) + return err; + + diff_u16 = (sqfs_u16 *)&ent.inode_diff; + *diff_u16 = le16toh(*diff_u16); + + ent.offset = le16toh(ent.offset); + ent.type = le16toh(ent.type); + ent.size = le16toh(ent.size); + + out = calloc(1, sizeof(*out) + ent.size + 2); + if (out == NULL) + return SQFS_ERROR_ALLOC; + + *out = ent; + err = sqfs_meta_reader_read(m, out->name, ent.size + 1); + if (err) { + free(out); + return err; + } + + *result = out; + return 0; +} + +int sqfs_readdir_state_init(sqfs_readdir_state_t *s, const sqfs_super_t *super, + const sqfs_inode_generic_t *inode) +{ + memset(s, 0, sizeof(*s)); + + if (inode->base.type == SQFS_INODE_DIR) { + s->init.block = inode->data.dir.start_block; + s->init.offset = inode->data.dir.offset; + s->init.size = inode->data.dir.size; + } else if (inode->base.type == SQFS_INODE_EXT_DIR) { + s->init.block = inode->data.dir_ext.start_block; + s->init.offset = inode->data.dir_ext.offset; + s->init.size = inode->data.dir_ext.size; + } else { + return SQFS_ERROR_NOT_DIR; + } + + s->init.block += super->directory_table_start; + s->current = s->init; + return 0; +} + +int sqfs_meta_reader_readdir(sqfs_meta_reader_t *m, sqfs_readdir_state_t *it, + sqfs_dir_entry_t **ent, + sqfs_u32 *inum, sqfs_u64 *iref) +{ + size_t count; + int ret; + + if (it->entries == 0) { + sqfs_dir_header_t hdr; + + if (it->current.size <= sizeof(hdr)) + goto out_eof; + + ret = sqfs_meta_reader_seek(m, it->current.block, + it->current.offset); + if (ret != 0) + return ret; + + ret = sqfs_meta_reader_read_dir_header(m, &hdr); + if (ret != 0) + return ret; + + sqfs_meta_reader_get_position(m, &it->current.block, + &it->current.offset); + + it->current.size -= sizeof(hdr); + it->entries = hdr.count + 1; + it->inum_base = hdr.inode_number; + it->inode_block = hdr.start_block; + } + + if (it->current.size <= sizeof(**ent)) + goto out_eof; + + ret = sqfs_meta_reader_seek(m, it->current.block, it->current.offset); + if (ret != 0) + return ret; + + ret = sqfs_meta_reader_read_dir_ent(m, ent); + if (ret) + return ret; + + sqfs_meta_reader_get_position(m, &it->current.block, + &it->current.offset); + + it->current.size -= sizeof(**ent); + it->entries -= 1; + + count = (*ent)->size + 1; + + if (count >= it->current.size) { + it->current.size = 0; + } else { + it->current.size -= count; + } + + if (inum != NULL) + *inum = it->inum_base + (*ent)->inode_diff; + + if (iref != NULL) { + *iref = (sqfs_u64)it->inode_block << 16UL; + *iref |= (*ent)->offset; + } + + return 0; +out_eof: + it->current.size = 0; + it->entries = 0; + return 1; +} -- cgit v1.2.3