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