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