| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (C) 2020 Bootlin |
| * |
| * Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com> |
| */ |
| |
| #include <errno.h> |
| #include <linux/types.h> |
| #include <linux/byteorder/little_endian.h> |
| #include <linux/byteorder/generic.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "sqfs_filesystem.h" |
| #include "sqfs_utils.h" |
| |
| bool sqfs_is_dir(u16 type) |
| { |
| return type == SQFS_DIR_TYPE || type == SQFS_LDIR_TYPE; |
| } |
| |
| /* |
| * Receives a pointer (void *) to a position in the inode table containing the |
| * directory's inode. Returns directory inode offset into the directory table. |
| * m_list contains each metadata block's position, and m_count is the number of |
| * elements of m_list. Those metadata blocks come from the compressed directory |
| * table. |
| */ |
| int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count) |
| { |
| struct squashfs_base_inode *base = dir_i; |
| struct squashfs_ldir_inode *ldir; |
| struct squashfs_dir_inode *dir; |
| u32 start_block; |
| int j, offset; |
| |
| switch (get_unaligned_le16(&base->inode_type)) { |
| case SQFS_DIR_TYPE: |
| dir = (struct squashfs_dir_inode *)base; |
| start_block = get_unaligned_le32(&dir->start_block); |
| offset = get_unaligned_le16(&dir->offset); |
| break; |
| case SQFS_LDIR_TYPE: |
| ldir = (struct squashfs_ldir_inode *)base; |
| start_block = get_unaligned_le32(&ldir->start_block); |
| offset = get_unaligned_le16(&ldir->offset); |
| break; |
| default: |
| printf("Error: this is not a directory.\n"); |
| return -EINVAL; |
| } |
| |
| if (offset < 0) |
| return -EINVAL; |
| |
| for (j = 0; j < m_count; j++) { |
| if (m_list[j] == start_block) |
| return (++j * SQFS_METADATA_BLOCK_SIZE) + offset; |
| } |
| |
| if (start_block == 0) |
| return offset; |
| |
| printf("Error: invalid inode reference to directory table.\n"); |
| |
| return -EINVAL; |
| } |
| |
| bool sqfs_is_empty_dir(void *dir_i) |
| { |
| struct squashfs_base_inode *base = dir_i; |
| struct squashfs_ldir_inode *ldir; |
| struct squashfs_dir_inode *dir; |
| u32 file_size; |
| |
| switch (get_unaligned_le16(&base->inode_type)) { |
| case SQFS_DIR_TYPE: |
| dir = (struct squashfs_dir_inode *)base; |
| file_size = get_unaligned_le16(&dir->file_size); |
| break; |
| case SQFS_LDIR_TYPE: |
| ldir = (struct squashfs_ldir_inode *)base; |
| file_size = get_unaligned_le16(&ldir->file_size); |
| break; |
| default: |
| printf("Error: this is not a directory.\n"); |
| return false; |
| } |
| |
| return file_size == SQFS_EMPTY_FILE_SIZE; |
| } |