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