1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 Bootlin 4 * 5 * Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com> 6 */ 7 8#include <errno.h> 9#include <linux/types.h> 10#include <asm/byteorder.h> 11#include <stdint.h> 12#include <stdio.h> 13#include <stdlib.h> 14 15#include "sqfs_filesystem.h" 16#include "sqfs_utils.h" 17 18bool sqfs_is_dir(u16 type) 19{ 20 return type == SQFS_DIR_TYPE || type == SQFS_LDIR_TYPE; 21} 22 23/* 24 * Receives a pointer (void *) to a position in the inode table containing the 25 * directory's inode. Returns directory inode offset into the directory table. 26 * m_list contains each metadata block's position, and m_count is the number of 27 * elements of m_list. Those metadata blocks come from the compressed directory 28 * table. 29 */ 30int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count) 31{ 32 struct squashfs_base_inode *base = dir_i; 33 struct squashfs_ldir_inode *ldir; 34 struct squashfs_dir_inode *dir; 35 u32 start_block; 36 int j, offset; 37 38 switch (get_unaligned_le16(&base->inode_type)) { 39 case SQFS_DIR_TYPE: 40 dir = (struct squashfs_dir_inode *)base; 41 start_block = get_unaligned_le32(&dir->start_block); 42 offset = get_unaligned_le16(&dir->offset); 43 break; 44 case SQFS_LDIR_TYPE: 45 ldir = (struct squashfs_ldir_inode *)base; 46 start_block = get_unaligned_le32(&ldir->start_block); 47 offset = get_unaligned_le16(&ldir->offset); 48 break; 49 default: 50 printf("Error: this is not a directory.\n"); 51 return -EINVAL; 52 } 53 54 if (offset < 0) 55 return -EINVAL; 56 57 for (j = 0; j < m_count; j++) { 58 if (m_list[j] == start_block) 59 return (++j * SQFS_METADATA_BLOCK_SIZE) + offset; 60 } 61 62 if (start_block == 0) 63 return offset; 64 65 printf("Error: invalid inode reference to directory table.\n"); 66 67 return -EINVAL; 68} 69 70bool sqfs_is_empty_dir(void *dir_i) 71{ 72 struct squashfs_base_inode *base = dir_i; 73 struct squashfs_ldir_inode *ldir; 74 struct squashfs_dir_inode *dir; 75 u32 file_size; 76 77 switch (get_unaligned_le16(&base->inode_type)) { 78 case SQFS_DIR_TYPE: 79 dir = (struct squashfs_dir_inode *)base; 80 file_size = get_unaligned_le16(&dir->file_size); 81 break; 82 case SQFS_LDIR_TYPE: 83 ldir = (struct squashfs_ldir_inode *)base; 84 file_size = get_unaligned_le16(&ldir->file_size); 85 break; 86 default: 87 printf("Error: this is not a directory.\n"); 88 return false; 89 } 90 91 return file_size == SQFS_EMPTY_FILE_SIZE; 92} 93