aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/read_inode.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 11:21:30 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 13:51:49 +0100
commitcdccc69c62579b0c13b35fad0728079652b8f3c9 (patch)
tree9fa54c710f73c5e08a9c8466e7a712eb63ee07ac /lib/sqfs/read_inode.c
parent2182129c8f359c4fa1390eaba7a65b595ccd4182 (diff)
Move library source into src sub-directory
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/read_inode.c')
-rw-r--r--lib/sqfs/read_inode.c424
1 files changed, 0 insertions, 424 deletions
diff --git a/lib/sqfs/read_inode.c b/lib/sqfs/read_inode.c
deleted file mode 100644
index 12bef48..0000000
--- a/lib/sqfs/read_inode.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * read_inode.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#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 "util/util.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#define SWAB16(x) x = le16toh(x)
-#define SWAB32(x) x = le32toh(x)
-#define SWAB64(x) x = le64toh(x)
-
-static int set_mode(sqfs_inode_t *inode)
-{
- inode->mode &= ~S_IFMT;
-
- switch (inode->type) {
- case SQFS_INODE_SOCKET:
- case SQFS_INODE_EXT_SOCKET:
- inode->mode |= S_IFSOCK;
- break;
- case SQFS_INODE_SLINK:
- case SQFS_INODE_EXT_SLINK:
- inode->mode |= S_IFLNK;
- break;
- case SQFS_INODE_FILE:
- case SQFS_INODE_EXT_FILE:
- inode->mode |= S_IFREG;
- break;
- case SQFS_INODE_BDEV:
- case SQFS_INODE_EXT_BDEV:
- inode->mode |= S_IFBLK;
- break;
- case SQFS_INODE_DIR:
- case SQFS_INODE_EXT_DIR:
- inode->mode |= S_IFDIR;
- break;
- case SQFS_INODE_CDEV:
- case SQFS_INODE_EXT_CDEV:
- inode->mode |= S_IFCHR;
- break;
- case SQFS_INODE_FIFO:
- case SQFS_INODE_EXT_FIFO:
- inode->mode |= S_IFIFO;
- break;
- default:
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- return 0;
-}
-
-static sqfs_u64 get_block_count(sqfs_u64 size, sqfs_u64 block_size,
- sqfs_u32 frag_index, sqfs_u32 frag_offset)
-{
- sqfs_u64 count = size / block_size;
-
- if ((size % block_size) != 0 &&
- (frag_index == 0xFFFFFFFF || frag_offset == 0xFFFFFFFF)) {
- ++count;
- }
-
- return count;
-}
-
-static int read_inode_file(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
- size_t block_size, sqfs_inode_generic_t **result)
-{
- sqfs_inode_generic_t *out;
- sqfs_inode_file_t file;
- sqfs_u64 i, count;
- int err;
-
- err = sqfs_meta_reader_read(ir, &file, sizeof(file));
- if (err)
- return err;
-
- SWAB32(file.blocks_start);
- SWAB32(file.fragment_index);
- SWAB32(file.fragment_offset);
- SWAB32(file.file_size);
-
- count = get_block_count(file.file_size, block_size,
- file.fragment_index, file.fragment_offset);
-
- out = alloc_flex(sizeof(*out), sizeof(sqfs_u32), count);
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- out->base = *base;
- out->data.file = file;
- out->payload_bytes_available = count * sizeof(sqfs_u32);
- out->payload_bytes_used = count * sizeof(sqfs_u32);
-
- err = sqfs_meta_reader_read(ir, out->extra, count * sizeof(sqfs_u32));
- if (err) {
- free(out);
- return err;
- }
-
- for (i = 0; i < count; ++i)
- SWAB32(out->extra[i]);
-
- *result = out;
- return 0;
-}
-
-static int read_inode_file_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
- size_t block_size, sqfs_inode_generic_t **result)
-{
- sqfs_inode_file_ext_t file;
- sqfs_inode_generic_t *out;
- sqfs_u64 i, count;
- int err;
-
- err = sqfs_meta_reader_read(ir, &file, sizeof(file));
- if (err)
- return err;
-
- SWAB64(file.blocks_start);
- SWAB64(file.file_size);
- SWAB64(file.sparse);
- SWAB32(file.nlink);
- SWAB32(file.fragment_idx);
- SWAB32(file.fragment_offset);
- SWAB32(file.xattr_idx);
-
- count = get_block_count(file.file_size, block_size,
- file.fragment_idx, file.fragment_offset);
-
- out = alloc_flex(sizeof(*out), sizeof(sqfs_u32), count);
- if (out == NULL) {
- return errno == EOVERFLOW ? SQFS_ERROR_OVERFLOW :
- SQFS_ERROR_ALLOC;
- }
-
- out->base = *base;
- out->data.file_ext = file;
- out->payload_bytes_available = count * sizeof(sqfs_u32);
- out->payload_bytes_used = count * sizeof(sqfs_u32);
-
- err = sqfs_meta_reader_read(ir, out->extra, count * sizeof(sqfs_u32));
- if (err) {
- free(out);
- return err;
- }
-
- for (i = 0; i < count; ++i)
- SWAB32(out->extra[i]);
-
- *result = out;
- return 0;
-}
-
-static int read_inode_slink(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
- sqfs_inode_generic_t **result)
-{
- sqfs_inode_generic_t *out;
- sqfs_inode_slink_t slink;
- size_t size;
- int err;
-
- err = sqfs_meta_reader_read(ir, &slink, sizeof(slink));
- if (err)
- return err;
-
- SWAB32(slink.nlink);
- SWAB32(slink.target_size);
-
- if (SZ_ADD_OV(slink.target_size, 1, &size) ||
- SZ_ADD_OV(sizeof(*out), size, &size)) {
- return SQFS_ERROR_OVERFLOW;
- }
-
- out = calloc(1, size);
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- out->payload_bytes_available = size - sizeof(*out);
- out->payload_bytes_used = size - sizeof(*out) - 1;
- out->base = *base;
- out->data.slink = slink;
-
- err = sqfs_meta_reader_read(ir, (void *)out->extra, slink.target_size);
- if (err) {
- free(out);
- return err;
- }
-
- *result = out;
- return 0;
-}
-
-static int read_inode_slink_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
- sqfs_inode_generic_t **result)
-{
- sqfs_u32 xattr;
- int err;
-
- err = read_inode_slink(ir, base, result);
- if (err)
- return err;
-
- err = sqfs_meta_reader_read(ir, &xattr, sizeof(xattr));
- if (err) {
- free(*result);
- return err;
- }
-
- (*result)->data.slink_ext.xattr_idx = le32toh(xattr);
- return 0;
-}
-
-static int read_inode_dir_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
- sqfs_inode_generic_t **result)
-{
- size_t i, new_sz, index_max, index_used;
- sqfs_inode_generic_t *out, *new;
- sqfs_inode_dir_ext_t dir;
- sqfs_dir_index_t ent;
- int err;
-
- err = sqfs_meta_reader_read(ir, &dir, sizeof(dir));
- if (err)
- return err;
-
- SWAB32(dir.nlink);
- SWAB32(dir.size);
- SWAB32(dir.start_block);
- SWAB32(dir.parent_inode);
- SWAB16(dir.inodex_count);
- SWAB16(dir.offset);
- SWAB32(dir.xattr_idx);
-
- index_max = dir.size ? 128 : 0;
- index_used = 0;
-
- out = alloc_flex(sizeof(*out), 1, index_max);
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- out->base = *base;
- out->data.dir_ext = dir;
-
- if (dir.size == 0) {
- *result = out;
- return 0;
- }
-
- for (i = 0; i < dir.inodex_count; ++i) {
- err = sqfs_meta_reader_read(ir, &ent, sizeof(ent));
- if (err) {
- free(out);
- return err;
- }
-
- SWAB32(ent.start_block);
- SWAB32(ent.index);
- SWAB32(ent.size);
-
- new_sz = index_max;
- while (sizeof(ent) + ent.size + 1 > new_sz - index_used) {
- if (SZ_MUL_OV(new_sz, 2, &new_sz)) {
- free(out);
- return SQFS_ERROR_OVERFLOW;
- }
- }
-
- if (new_sz > index_max) {
- new = realloc(out, sizeof(*out) + new_sz);
- if (new == NULL) {
- free(out);
- return SQFS_ERROR_ALLOC;
- }
- out = new;
- index_max = new_sz;
- }
-
- memcpy((char *)out->extra + index_used, &ent, sizeof(ent));
- index_used += sizeof(ent);
-
- err = sqfs_meta_reader_read(ir, (char *)out->extra + index_used,
- ent.size + 1);
- if (err) {
- free(out);
- return err;
- }
-
- index_used += ent.size + 1;
- }
-
- out->payload_bytes_used = index_used;
- out->payload_bytes_available = index_used;
- *result = out;
- return 0;
-}
-
-int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir,
- const sqfs_super_t *super,
- sqfs_u64 block_start, size_t offset,
- sqfs_inode_generic_t **result)
-{
- sqfs_inode_generic_t *out;
- sqfs_inode_t inode;
- int err;
-
- /* read base inode */
- block_start += super->inode_table_start;
-
- err = sqfs_meta_reader_seek(ir, block_start, offset);
- if (err)
- return err;
-
- err = sqfs_meta_reader_read(ir, &inode, sizeof(inode));
- if (err)
- return err;
-
- SWAB16(inode.type);
- SWAB16(inode.mode);
- SWAB16(inode.uid_idx);
- SWAB16(inode.gid_idx);
- SWAB32(inode.mod_time);
- SWAB32(inode.inode_number);
-
- err = set_mode(&inode);
- if (err)
- return err;
-
- /* inode types where the size is variable */
- switch (inode.type) {
- case SQFS_INODE_FILE:
- return read_inode_file(ir, &inode, super->block_size, result);
- case SQFS_INODE_SLINK:
- return read_inode_slink(ir, &inode, result);
- case SQFS_INODE_EXT_FILE:
- return read_inode_file_ext(ir, &inode, super->block_size,
- result);
- case SQFS_INODE_EXT_SLINK:
- return read_inode_slink_ext(ir, &inode, result);
- case SQFS_INODE_EXT_DIR:
- return read_inode_dir_ext(ir, &inode, result);
- default:
- break;
- }
-
- /* everything else */
- out = calloc(1, sizeof(*out));
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- out->base = inode;
-
- switch (inode.type) {
- case SQFS_INODE_DIR:
- err = sqfs_meta_reader_read(ir, &out->data.dir,
- sizeof(out->data.dir));
- if (err)
- goto fail_free;
-
- SWAB32(out->data.dir.start_block);
- SWAB32(out->data.dir.nlink);
- SWAB16(out->data.dir.size);
- SWAB16(out->data.dir.offset);
- SWAB32(out->data.dir.parent_inode);
- break;
- case SQFS_INODE_BDEV:
- case SQFS_INODE_CDEV:
- err = sqfs_meta_reader_read(ir, &out->data.dev,
- sizeof(out->data.dev));
- if (err)
- goto fail_free;
- SWAB32(out->data.dev.nlink);
- SWAB32(out->data.dev.devno);
- break;
- case SQFS_INODE_FIFO:
- case SQFS_INODE_SOCKET:
- err = sqfs_meta_reader_read(ir, &out->data.ipc,
- sizeof(out->data.ipc));
- if (err)
- goto fail_free;
- SWAB32(out->data.ipc.nlink);
- break;
- case SQFS_INODE_EXT_BDEV:
- case SQFS_INODE_EXT_CDEV:
- err = sqfs_meta_reader_read(ir, &out->data.dev_ext,
- sizeof(out->data.dev_ext));
- if (err)
- goto fail_free;
- SWAB32(out->data.dev_ext.nlink);
- SWAB32(out->data.dev_ext.devno);
- SWAB32(out->data.dev_ext.xattr_idx);
- break;
- case SQFS_INODE_EXT_FIFO:
- case SQFS_INODE_EXT_SOCKET:
- err = sqfs_meta_reader_read(ir, &out->data.ipc_ext,
- sizeof(out->data.ipc_ext));
- if (err)
- goto fail_free;
- SWAB32(out->data.ipc_ext.nlink);
- SWAB32(out->data.ipc_ext.xattr_idx);
- break;
- default:
- err = SQFS_ERROR_UNSUPPORTED;
- goto fail_free;
- }
-
- *result = out;
- return 0;
-fail_free:
- free(out);
- return err;
-}