blob: 5440b6c0e05985a775872b5f8c8ce73ef05f1137 [file] [log] [blame]
Joao Marcos Costa29da3742020-07-30 15:33:47 +02001/* 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#ifndef SQFS_FILESYSTEM_H
9#define SQFS_FILESYSTEM_H
10
11#include <asm/unaligned.h>
Joao Marcos Costa29da3742020-07-30 15:33:47 +020012#include <fs.h>
Joao Marcos Costa877576c2020-08-18 17:17:21 +020013#include <part.h>
14#include <stdint.h>
Joao Marcos Costa29da3742020-07-30 15:33:47 +020015
16#define SQFS_UNCOMPRESSED_DATA 0x0002
17#define SQFS_MAGIC_NUMBER 0x73717368
18/* The three first members of squashfs_dir_index make a total of 12 bytes */
19#define SQFS_DIR_INDEX_BASE_LENGTH 12
20/* size of metadata (inode and directory) blocks */
21#define SQFS_METADATA_BLOCK_SIZE 8192
22/* Max. number of fragment entries in a metadata block is 512 */
23#define SQFS_MAX_ENTRIES 512
24/* Metadata blocks start by a 2-byte length header */
25#define SQFS_HEADER_SIZE 2
26#define SQFS_LREG_INODE_MIN_SIZE 56
27#define SQFS_DIR_HEADER_SIZE 12
28#define SQFS_MISC_ENTRY_TYPE -1
29#define SQFS_EMPTY_FILE_SIZE 3
30#define SQFS_STOP_READDIR 1
31#define SQFS_EMPTY_DIR -1
32/*
33 * A directory entry object has a fixed length of 8 bytes, corresponding to its
34 * first four members, plus the size of the entry name, which is equal to
35 * 'entry_name' + 1 bytes.
36 */
37#define SQFS_ENTRY_BASE_LENGTH 8
38/* Inode types */
39#define SQFS_DIR_TYPE 1
40#define SQFS_REG_TYPE 2
41#define SQFS_SYMLINK_TYPE 3
42#define SQFS_BLKDEV_TYPE 4
43#define SQFS_CHRDEV_TYPE 5
44#define SQFS_FIFO_TYPE 6
45#define SQFS_SOCKET_TYPE 7
46#define SQFS_LDIR_TYPE 8
47#define SQFS_LREG_TYPE 9
48#define SQFS_LSYMLINK_TYPE 10
49#define SQFS_LBLKDEV_TYPE 11
50#define SQFS_LCHRDEV_TYPE 12
51#define SQFS_LFIFO_TYPE 13
52#define SQFS_LSOCKET_TYPE 14
53
54struct squashfs_super_block {
55 __le32 s_magic;
56 __le32 inodes;
57 __le32 mkfs_time;
58 __le32 block_size;
59 __le32 fragments;
60 __le16 compression;
61 __le16 block_log;
62 __le16 flags;
63 __le16 no_ids;
64 __le16 s_major;
65 __le16 s_minor;
66 __le64 root_inode;
67 __le64 bytes_used;
68 __le64 id_table_start;
69 __le64 xattr_id_table_start;
70 __le64 inode_table_start;
71 __le64 directory_table_start;
72 __le64 fragment_table_start;
73 __le64 export_table_start;
74};
75
Joao Marcos Costa877576c2020-08-18 17:17:21 +020076struct squashfs_ctxt {
77 struct disk_partition cur_part_info;
78 struct blk_desc *cur_dev;
79 struct squashfs_super_block *sblk;
Joao Marcos Costab1fa6b82020-08-18 17:17:23 +020080#if IS_ENABLED(CONFIG_ZSTD)
81 void *zstd_workspace;
82#endif
Joao Marcos Costa877576c2020-08-18 17:17:21 +020083};
84
Joao Marcos Costa29da3742020-07-30 15:33:47 +020085struct squashfs_directory_index {
86 u32 index;
87 u32 start;
88 u32 size;
89 char name[0];
90};
91
92struct squashfs_base_inode {
93 __le16 inode_type;
94 __le16 mode;
95 __le16 uid;
96 __le16 guid;
97 __le32 mtime;
98 __le32 inode_number;
99};
100
101struct squashfs_ipc_inode {
102 __le16 inode_type;
103 __le16 mode;
104 __le16 uid;
105 __le16 guid;
106 __le32 mtime;
107 __le32 inode_number;
108 __le32 nlink;
109};
110
111struct squashfs_lipc_inode {
112 __le16 inode_type;
113 __le16 mode;
114 __le16 uid;
115 __le16 guid;
116 __le32 mtime;
117 __le32 inode_number;
118 __le32 nlink;
119 __le32 xattr;
120};
121
122struct squashfs_dev_inode {
123 __le16 inode_type;
124 __le16 mode;
125 __le16 uid;
126 __le16 guid;
127 __le32 mtime;
128 __le32 inode_number;
129 __le32 nlink;
130 __le32 rdev;
131};
132
133struct squashfs_ldev_inode {
134 __le16 inode_type;
135 __le16 mode;
136 __le16 uid;
137 __le16 guid;
138 __le32 mtime;
139 __le32 inode_number;
140 __le32 nlink;
141 __le32 rdev;
142 __le32 xattr;
143};
144
145struct squashfs_symlink_inode {
146 __le16 inode_type;
147 __le16 mode;
148 __le16 uid;
149 __le16 guid;
150 __le32 mtime;
151 __le32 inode_number;
152 __le32 nlink;
153 __le32 symlink_size;
154 char symlink[0];
155};
156
157struct squashfs_reg_inode {
158 __le16 inode_type;
159 __le16 mode;
160 __le16 uid;
161 __le16 guid;
162 __le32 mtime;
163 __le32 inode_number;
164 __le32 start_block;
165 __le32 fragment;
166 __le32 offset;
167 __le32 file_size;
168 __le32 block_list[0];
169};
170
171struct squashfs_lreg_inode {
172 __le16 inode_type;
173 __le16 mode;
174 __le16 uid;
175 __le16 guid;
176 __le32 mtime;
177 __le32 inode_number;
178 __le64 start_block;
179 __le64 file_size;
180 __le64 sparse;
181 __le32 nlink;
182 __le32 fragment;
183 __le32 offset;
184 __le32 xattr;
185 __le32 block_list[0];
186};
187
188struct squashfs_dir_inode {
189 __le16 inode_type;
190 __le16 mode;
191 __le16 uid;
192 __le16 guid;
193 __le32 mtime;
194 __le32 inode_number;
195 __le32 start_block;
196 __le32 nlink;
197 __le16 file_size;
198 __le16 offset;
199 __le32 parent_inode;
200};
201
202struct squashfs_ldir_inode {
203 __le16 inode_type;
204 __le16 mode;
205 __le16 uid;
206 __le16 guid;
207 __le32 mtime;
208 __le32 inode_number;
209 __le32 nlink;
210 __le32 file_size;
211 __le32 start_block;
212 __le32 parent_inode;
213 __le16 i_count;
214 __le16 offset;
215 __le32 xattr;
216 struct squashfs_directory_index index[0];
217};
218
219union squashfs_inode {
220 struct squashfs_base_inode *base;
221 struct squashfs_dev_inode *dev;
222 struct squashfs_ldev_inode *ldev;
223 struct squashfs_symlink_inode *symlink;
224 struct squashfs_reg_inode *reg;
225 struct squashfs_lreg_inode *lreg;
226 struct squashfs_dir_inode *dir;
227 struct squashfs_ldir_inode *ldir;
228 struct squashfs_ipc_inode *ipc;
229 struct squashfs_lipc_inode *lipc;
230};
231
232struct squashfs_directory_entry {
233 u16 offset;
Campbell Suter4e8f02d2021-04-30 16:45:46 +1200234 s16 inode_offset;
Joao Marcos Costa29da3742020-07-30 15:33:47 +0200235 u16 type;
236 u16 name_size;
237 char name[0];
238};
239
240struct squashfs_directory_header {
241 u32 count;
242 u32 start;
243 u32 inode_number;
244};
245
246struct squashfs_fragment_block_entry {
247 u64 start;
248 u32 size;
249 u32 _unused;
250};
251
252struct squashfs_dir_stream {
253 struct fs_dir_stream fs_dirs;
254 struct fs_dirent dentp;
255 /*
256 * 'size' is the uncompressed size of the entire listing, including
257 * headers. 'entry_count' is the number of entries following a
258 * specific header. Both variables are decremented in sqfs_readdir() so
259 * the function knows when the end of the directory is reached.
260 */
261 size_t size;
262 int entry_count;
263 /* SquashFS structures */
264 struct squashfs_directory_header *dir_header;
265 struct squashfs_directory_entry *entry;
266 /*
267 * 'table' points to a position into the directory table. Both 'table'
268 * and 'inode' are defined for the first time in sqfs_opendir().
269 * 'table's value changes in sqfs_readdir().
270 */
271 unsigned char *table;
272 union squashfs_inode i;
273 struct squashfs_dir_inode i_dir;
274 struct squashfs_ldir_inode i_ldir;
275 /*
276 * References to the tables' beginnings. They are assigned in
277 * sqfs_opendir() and freed in sqfs_closedir().
278 */
279 unsigned char *inode_table;
280 unsigned char *dir_table;
281};
282
283struct squashfs_file_info {
284 /* File size in bytes (uncompressed) */
285 size_t size;
286 /* Reference to list of data blocks's sizes */
287 u32 *blk_sizes;
288 /* Offset into the fragment block */
289 u32 offset;
290 /* Offset in which the data blocks begin */
291 u64 start;
292 /* Is file fragmented? */
293 bool frag;
294 /* Compressed fragment */
295 bool comp;
296};
297
298void *sqfs_find_inode(void *inode_table, int inode_number, __le32 inode_count,
299 __le32 block_size);
300
301int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count);
302
303int sqfs_read_metablock(unsigned char *file_mapping, int offset,
304 bool *compressed, u32 *data_size);
305
306bool sqfs_is_empty_dir(void *dir_i);
307
308bool sqfs_is_dir(u16 type);
309
310#endif /* SQFS_FILESYSTEM_H */