summaryrefslogtreecommitdiff
path: root/fs/squashfs/sqfs_filesystem.h
diff options
context:
space:
mode:
Diffstat (limited to 'fs/squashfs/sqfs_filesystem.h')
-rw-r--r--fs/squashfs/sqfs_filesystem.h300
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 */