diff options
Diffstat (limited to 'fs/squashfs/sqfs_filesystem.h')
-rw-r--r-- | fs/squashfs/sqfs_filesystem.h | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/fs/squashfs/sqfs_filesystem.h b/fs/squashfs/sqfs_filesystem.h new file mode 100644 index 0000000000..d63e3a41ad --- /dev/null +++ b/fs/squashfs/sqfs_filesystem.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Bootlin + * + * Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com> + */ + +#ifndef SQFS_FILESYSTEM_H +#define SQFS_FILESYSTEM_H + +#include <asm/unaligned.h> +#include <stdint.h> +#include <fs.h> + +#define SQFS_UNCOMPRESSED_DATA 0x0002 +#define SQFS_MAGIC_NUMBER 0x73717368 +/* The three first members of squashfs_dir_index make a total of 12 bytes */ +#define SQFS_DIR_INDEX_BASE_LENGTH 12 +/* size of metadata (inode and directory) blocks */ +#define SQFS_METADATA_BLOCK_SIZE 8192 +/* Max. number of fragment entries in a metadata block is 512 */ +#define SQFS_MAX_ENTRIES 512 +/* Metadata blocks start by a 2-byte length header */ +#define SQFS_HEADER_SIZE 2 +#define SQFS_LREG_INODE_MIN_SIZE 56 +#define SQFS_DIR_HEADER_SIZE 12 +#define SQFS_MISC_ENTRY_TYPE -1 +#define SQFS_EMPTY_FILE_SIZE 3 +#define SQFS_STOP_READDIR 1 +#define SQFS_EMPTY_DIR -1 +/* + * A directory entry object has a fixed length of 8 bytes, corresponding to its + * first four members, plus the size of the entry name, which is equal to + * 'entry_name' + 1 bytes. + */ +#define SQFS_ENTRY_BASE_LENGTH 8 +/* Inode types */ +#define SQFS_DIR_TYPE 1 +#define SQFS_REG_TYPE 2 +#define SQFS_SYMLINK_TYPE 3 +#define SQFS_BLKDEV_TYPE 4 +#define SQFS_CHRDEV_TYPE 5 +#define SQFS_FIFO_TYPE 6 +#define SQFS_SOCKET_TYPE 7 +#define SQFS_LDIR_TYPE 8 +#define SQFS_LREG_TYPE 9 +#define SQFS_LSYMLINK_TYPE 10 +#define SQFS_LBLKDEV_TYPE 11 +#define SQFS_LCHRDEV_TYPE 12 +#define SQFS_LFIFO_TYPE 13 +#define SQFS_LSOCKET_TYPE 14 + +struct squashfs_super_block { + __le32 s_magic; + __le32 inodes; + __le32 mkfs_time; + __le32 block_size; + __le32 fragments; + __le16 compression; + __le16 block_log; + __le16 flags; + __le16 no_ids; + __le16 s_major; + __le16 s_minor; + __le64 root_inode; + __le64 bytes_used; + __le64 id_table_start; + __le64 xattr_id_table_start; + __le64 inode_table_start; + __le64 directory_table_start; + __le64 fragment_table_start; + __le64 export_table_start; +}; + +struct squashfs_directory_index { + u32 index; + u32 start; + u32 size; + char name[0]; +}; + +struct squashfs_base_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; +}; + +struct squashfs_ipc_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; +}; + +struct squashfs_lipc_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; + __le32 xattr; +}; + +struct squashfs_dev_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; + __le32 rdev; +}; + +struct squashfs_ldev_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; + __le32 rdev; + __le32 xattr; +}; + +struct squashfs_symlink_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; + __le32 symlink_size; + char symlink[0]; +}; + +struct squashfs_reg_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 start_block; + __le32 fragment; + __le32 offset; + __le32 file_size; + __le32 block_list[0]; +}; + +struct squashfs_lreg_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le64 start_block; + __le64 file_size; + __le64 sparse; + __le32 nlink; + __le32 fragment; + __le32 offset; + __le32 xattr; + __le32 block_list[0]; +}; + +struct squashfs_dir_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 start_block; + __le32 nlink; + __le16 file_size; + __le16 offset; + __le32 parent_inode; +}; + +struct squashfs_ldir_inode { + __le16 inode_type; + __le16 mode; + __le16 uid; + __le16 guid; + __le32 mtime; + __le32 inode_number; + __le32 nlink; + __le32 file_size; + __le32 start_block; + __le32 parent_inode; + __le16 i_count; + __le16 offset; + __le32 xattr; + struct squashfs_directory_index index[0]; +}; + +union squashfs_inode { + struct squashfs_base_inode *base; + struct squashfs_dev_inode *dev; + struct squashfs_ldev_inode *ldev; + struct squashfs_symlink_inode *symlink; + struct squashfs_reg_inode *reg; + struct squashfs_lreg_inode *lreg; + struct squashfs_dir_inode *dir; + struct squashfs_ldir_inode *ldir; + struct squashfs_ipc_inode *ipc; + struct squashfs_lipc_inode *lipc; +}; + +struct squashfs_directory_entry { + u16 offset; + u16 inode_offset; + u16 type; + u16 name_size; + char name[0]; +}; + +struct squashfs_directory_header { + u32 count; + u32 start; + u32 inode_number; +}; + +struct squashfs_fragment_block_entry { + u64 start; + u32 size; + u32 _unused; +}; + +struct squashfs_dir_stream { + struct fs_dir_stream fs_dirs; + struct fs_dirent dentp; + /* + * 'size' is the uncompressed size of the entire listing, including + * headers. 'entry_count' is the number of entries following a + * specific header. Both variables are decremented in sqfs_readdir() so + * the function knows when the end of the directory is reached. + */ + size_t size; + int entry_count; + /* SquashFS structures */ + struct squashfs_directory_header *dir_header; + struct squashfs_directory_entry *entry; + /* + * 'table' points to a position into the directory table. Both 'table' + * and 'inode' are defined for the first time in sqfs_opendir(). + * 'table's value changes in sqfs_readdir(). + */ + unsigned char *table; + union squashfs_inode i; + struct squashfs_dir_inode i_dir; + struct squashfs_ldir_inode i_ldir; + /* + * References to the tables' beginnings. They are assigned in + * sqfs_opendir() and freed in sqfs_closedir(). + */ + unsigned char *inode_table; + unsigned char *dir_table; +}; + +struct squashfs_file_info { + /* File size in bytes (uncompressed) */ + size_t size; + /* Reference to list of data blocks's sizes */ + u32 *blk_sizes; + /* Offset into the fragment block */ + u32 offset; + /* Offset in which the data blocks begin */ + u64 start; + /* Is file fragmented? */ + bool frag; + /* Compressed fragment */ + bool comp; +}; + +void *sqfs_find_inode(void *inode_table, int inode_number, __le32 inode_count, + __le32 block_size); + +int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count); + +int sqfs_read_metablock(unsigned char *file_mapping, int offset, + bool *compressed, u32 *data_size); + +bool sqfs_is_empty_dir(void *dir_i); + +bool sqfs_is_dir(u16 type); + +#endif /* SQFS_FILESYSTEM_H */ |