• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SQUASHFS_FS
2 #define SQUASHFS_FS
3 
4 /*
5  * Squashfs
6  *
7  * Copyright (c) 2002, 2003, 2004, 2005, 2006
8  * Phillip Lougher <phillip@lougher.demon.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2,
13  * or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  *
24  * squashfs_fs.h
25  */
26 
27 #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
28 #define CONFIG_SQUASHFS_2_0_COMPATIBILITY
29 #endif
30 
31 #ifdef CONFIG_SQUASHFS_VMALLOC
32 #define SQUASHFS_ALLOC(a)		vmalloc(a)
33 #define SQUASHFS_FREE(a)		vfree(a)
34 #else
35 #define SQUASHFS_ALLOC(a)		kmalloc(a, GFP_KERNEL)
36 #define SQUASHFS_FREE(a)		kfree(a)
37 #endif
38 #ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
39 #define SQUASHFS_CACHED_FRAGMENTS	CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
40 #else
41 #define SQUASHFS_CACHED_FRAGMENTS	3
42 #endif
43 #define SQUASHFS_MAJOR			3
44 #define SQUASHFS_MINOR			0
45 #define SQUASHFS_MAGIC			0x73717368
46 #define SQUASHFS_MAGIC_SWAP		0x68737173
47 #define SQUASHFS_START			0
48 
49 /* size of metadata (inode and directory) blocks */
50 #define SQUASHFS_METADATA_SIZE		8192
51 #define SQUASHFS_METADATA_LOG		13
52 
53 /* default size of data blocks */
54 #define SQUASHFS_FILE_SIZE		65536
55 #define SQUASHFS_FILE_LOG		16
56 
57 #define SQUASHFS_FILE_MAX_SIZE		65536
58 
59 /* Max number of uids and gids */
60 #define SQUASHFS_UIDS			256
61 #define SQUASHFS_GUIDS			255
62 
63 /* Max length of filename (not 255) */
64 #define SQUASHFS_NAME_LEN		256
65 
66 #define SQUASHFS_INVALID		((long long) 0xffffffffffff)
67 #define SQUASHFS_INVALID_FRAG		((unsigned int) 0xffffffff)
68 #define SQUASHFS_INVALID_BLK		((long long) -1)
69 #define SQUASHFS_USED_BLK		((long long) -2)
70 
71 /* Filesystem flags */
72 #define SQUASHFS_NOI			0
73 #define SQUASHFS_NOD			1
74 #define SQUASHFS_CHECK			2
75 #define SQUASHFS_NOF			3
76 #define SQUASHFS_NO_FRAG		4
77 #define SQUASHFS_ALWAYS_FRAG		5
78 #define SQUASHFS_DUPLICATE		6
79 
80 #define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
81 
82 #define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, \
83 						SQUASHFS_NOI)
84 
85 #define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, \
86 						SQUASHFS_NOD)
87 
88 #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
89 						SQUASHFS_NOF)
90 
91 #define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, \
92 						SQUASHFS_NO_FRAG)
93 
94 #define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
95 						SQUASHFS_ALWAYS_FRAG)
96 
97 #define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, \
98 						SQUASHFS_DUPLICATE)
99 
100 #define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, \
101 						SQUASHFS_CHECK)
102 
103 #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
104 		duplicate_checking)	(noi | (nod << 1) | (check_data << 2) \
105 		| (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
106 		(duplicate_checking << 6))
107 
108 /* Max number of types and file types */
109 #define SQUASHFS_DIR_TYPE		1
110 #define SQUASHFS_FILE_TYPE		2
111 #define SQUASHFS_SYMLINK_TYPE		3
112 #define SQUASHFS_BLKDEV_TYPE		4
113 #define SQUASHFS_CHRDEV_TYPE		5
114 #define SQUASHFS_FIFO_TYPE		6
115 #define SQUASHFS_SOCKET_TYPE		7
116 #define SQUASHFS_LDIR_TYPE		8
117 #define SQUASHFS_LREG_TYPE		9
118 
119 /* 1.0 filesystem type definitions */
120 #define SQUASHFS_TYPES			5
121 #define SQUASHFS_IPC_TYPE		0
122 
123 /* Flag whether block is compressed or uncompressed, bit is set if block is
124  * uncompressed */
125 #define SQUASHFS_COMPRESSED_BIT		(1 << 15)
126 
127 #define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
128 		(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
129 
130 #define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
131 
132 #define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
133 
134 #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	(((B) & \
135 	~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
136 	~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
137 
138 #define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
139 
140 /*
141  * Inode number ops.  Inodes consist of a compressed block number, and an
142  * uncompressed  offset within that block
143  */
144 #define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
145 
146 #define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
147 
148 #define SQUASHFS_MKINODE(A, B)		((squashfs_inode_t)(((squashfs_inode_t) (A)\
149 					<< 16) + (B)))
150 
151 /* Compute 32 bit VFS inode number from squashfs inode number */
152 #define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + \
153 					((b) >> 2) + 1))
154 /* XXX */
155 
156 /* Translate between VFS mode and squashfs mode */
157 #define SQUASHFS_MODE(a)		((a) & 0xfff)
158 
159 /* fragment and fragment table defines */
160 #define SQUASHFS_FRAGMENT_BYTES(A)	(A * sizeof(struct squashfs_fragment_entry))
161 
162 #define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / \
163 					SQUASHFS_METADATA_SIZE)
164 
165 #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % \
166 						SQUASHFS_METADATA_SIZE)
167 
168 #define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + \
169 					SQUASHFS_METADATA_SIZE - 1) / \
170 					SQUASHFS_METADATA_SIZE)
171 
172 #define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) *\
173 						sizeof(long long))
174 
175 /* cached data constants for filesystem */
176 #define SQUASHFS_CACHED_BLKS		8
177 
178 #define SQUASHFS_MAX_FILE_SIZE_LOG	64
179 
180 #define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << \
181 					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
182 
183 #define SQUASHFS_MARKER_BYTE		0xff
184 
185 /* meta index cache */
186 #define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
187 #define SQUASHFS_META_ENTRIES	31
188 #define SQUASHFS_META_NUMBER	8
189 #define SQUASHFS_SLOTS		4
190 
191 struct meta_entry {
192 	long long		data_block;
193 	unsigned int		index_block;
194 	unsigned short		offset;
195 	unsigned short		pad;
196 };
197 
198 struct meta_index {
199 	unsigned int		inode_number;
200 	unsigned int		offset;
201 	unsigned short		entries;
202 	unsigned short		skip;
203 	unsigned short		locked;
204 	unsigned short		pad;
205 	struct meta_entry	meta_entry[SQUASHFS_META_ENTRIES];
206 };
207 
208 
209 /*
210  * definitions for structures on disk
211  */
212 
213 typedef long long		squashfs_block_t;
214 typedef long long		squashfs_inode_t;
215 
216 struct squashfs_super_block {
217 	unsigned int		s_magic;
218 	unsigned int		inodes;
219 	unsigned int		bytes_used_2;
220 	unsigned int		uid_start_2;
221 	unsigned int		guid_start_2;
222 	unsigned int		inode_table_start_2;
223 	unsigned int		directory_table_start_2;
224 	unsigned int		s_major:16;
225 	unsigned int		s_minor:16;
226 	unsigned int		block_size_1:16;
227 	unsigned int		block_log:16;
228 	unsigned int		flags:8;
229 	unsigned int		no_uids:8;
230 	unsigned int		no_guids:8;
231 	unsigned int		mkfs_time /* time of filesystem creation */;
232 	squashfs_inode_t	root_inode;
233 	unsigned int		block_size;
234 	unsigned int		fragments;
235 	unsigned int		fragment_table_start_2;
236 	long long		bytes_used;
237 	long long		uid_start;
238 	long long		guid_start;
239 	long long		inode_table_start;
240 	long long		directory_table_start;
241 	long long		fragment_table_start;
242 	long long		unused;
243 } __attribute__ ((packed));
244 
245 struct squashfs_dir_index {
246 	unsigned int		index;
247 	unsigned int		start_block;
248 	unsigned char		size;
249 	unsigned char		name[0];
250 } __attribute__ ((packed));
251 
252 #define SQUASHFS_BASE_INODE_HEADER		\
253 	unsigned int		inode_type:4;	\
254 	unsigned int		mode:12;	\
255 	unsigned int		uid:8;		\
256 	unsigned int		guid:8;		\
257 	unsigned int		mtime;		\
258 	unsigned int 		inode_number;
259 
260 struct squashfs_base_inode_header {
261 	SQUASHFS_BASE_INODE_HEADER;
262 } __attribute__ ((packed));
263 
264 struct squashfs_ipc_inode_header {
265 	SQUASHFS_BASE_INODE_HEADER;
266 	unsigned int		nlink;
267 } __attribute__ ((packed));
268 
269 struct squashfs_dev_inode_header {
270 	SQUASHFS_BASE_INODE_HEADER;
271 	unsigned int		nlink;
272 	unsigned short		rdev;
273 } __attribute__ ((packed));
274 
275 struct squashfs_symlink_inode_header {
276 	SQUASHFS_BASE_INODE_HEADER;
277 	unsigned int		nlink;
278 	unsigned short		symlink_size;
279 	char			symlink[0];
280 } __attribute__ ((packed));
281 
282 struct squashfs_reg_inode_header {
283 	SQUASHFS_BASE_INODE_HEADER;
284 	squashfs_block_t	start_block;
285 	unsigned int		fragment;
286 	unsigned int		offset;
287 	unsigned int		file_size;
288 	unsigned short		block_list[0];
289 } __attribute__ ((packed));
290 
291 struct squashfs_lreg_inode_header {
292 	SQUASHFS_BASE_INODE_HEADER;
293 	unsigned int		nlink;
294 	squashfs_block_t	start_block;
295 	unsigned int		fragment;
296 	unsigned int		offset;
297 	long long		file_size;
298 	unsigned short		block_list[0];
299 } __attribute__ ((packed));
300 
301 struct squashfs_dir_inode_header {
302 	SQUASHFS_BASE_INODE_HEADER;
303 	unsigned int		nlink;
304 	unsigned int		file_size:19;
305 	unsigned int		offset:13;
306 	unsigned int		start_block;
307 	unsigned int		parent_inode;
308 } __attribute__  ((packed));
309 
310 struct squashfs_ldir_inode_header {
311 	SQUASHFS_BASE_INODE_HEADER;
312 	unsigned int		nlink;
313 	unsigned int		file_size:27;
314 	unsigned int		offset:13;
315 	unsigned int		start_block;
316 	unsigned int		i_count:16;
317 	unsigned int		parent_inode;
318 	struct squashfs_dir_index	index[0];
319 } __attribute__  ((packed));
320 
321 union squashfs_inode_header {
322 	struct squashfs_base_inode_header	base;
323 	struct squashfs_dev_inode_header	dev;
324 	struct squashfs_symlink_inode_header	symlink;
325 	struct squashfs_reg_inode_header	reg;
326 	struct squashfs_lreg_inode_header	lreg;
327 	struct squashfs_dir_inode_header	dir;
328 	struct squashfs_ldir_inode_header	ldir;
329 	struct squashfs_ipc_inode_header	ipc;
330 };
331 
332 struct squashfs_dir_entry {
333 	unsigned int		offset:13;
334 	unsigned int		type:3;
335 	unsigned int		size:8;
336 	int			inode_number:16;
337 	char			name[0];
338 } __attribute__ ((packed));
339 
340 struct squashfs_dir_header {
341 	unsigned int		count:8;
342 	unsigned int		start_block;
343 	unsigned int		inode_number;
344 } __attribute__ ((packed));
345 
346 struct squashfs_fragment_entry {
347 	long long		start_block;
348 	unsigned int		size;
349 	unsigned int		unused;
350 } __attribute__ ((packed));
351 
352 extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
353 extern int squashfs_uncompress_init(void);
354 extern int squashfs_uncompress_exit(void);
355 
356 /*
357  * macros to convert each packed bitfield structure from little endian to big
358  * endian and vice versa.  These are needed when creating or using a filesystem
359  * on a machine with different byte ordering to the target architecture.
360  *
361  */
362 
363 #define SQUASHFS_SWAP_START \
364 	int bits;\
365 	int b_pos;\
366 	unsigned long long val;\
367 	unsigned char *s;\
368 	unsigned char *d;
369 
370 #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
371 	SQUASHFS_SWAP_START\
372 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
373 	SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
374 	SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
375 	SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
376 	SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
377 	SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
378 	SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
379 	SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
380 	SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
381 	SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
382 	SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
383 	SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
384 	SQUASHFS_SWAP((s)->flags, d, 288, 8);\
385 	SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
386 	SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
387 	SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
388 	SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
389 	SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
390 	SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
391 	SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
392 	SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
393 	SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
394 	SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
395 	SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
396 	SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
397 	SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
398 	SQUASHFS_SWAP((s)->unused, d, 888, 64);\
399 }
400 
401 #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
402 	SQUASHFS_MEMSET(s, d, n);\
403 	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
404 	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
405 	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
406 	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
407 	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
408 	SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
409 
410 #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
411 	SQUASHFS_SWAP_START\
412 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
413 }
414 
415 #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
416 	SQUASHFS_SWAP_START\
417 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
418 			sizeof(struct squashfs_ipc_inode_header))\
419 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
420 }
421 
422 #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
423 	SQUASHFS_SWAP_START\
424 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
425 			sizeof(struct squashfs_dev_inode_header)); \
426 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
427 	SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
428 }
429 
430 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
431 	SQUASHFS_SWAP_START\
432 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
433 			sizeof(struct squashfs_symlink_inode_header));\
434 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
435 	SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
436 }
437 
438 #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
439 	SQUASHFS_SWAP_START\
440 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
441 			sizeof(struct squashfs_reg_inode_header));\
442 	SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
443 	SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
444 	SQUASHFS_SWAP((s)->offset, d, 192, 32);\
445 	SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
446 }
447 
448 #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
449 	SQUASHFS_SWAP_START\
450 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
451 			sizeof(struct squashfs_lreg_inode_header));\
452 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
453 	SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
454 	SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
455 	SQUASHFS_SWAP((s)->offset, d, 224, 32);\
456 	SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
457 }
458 
459 #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
460 	SQUASHFS_SWAP_START\
461 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
462 			sizeof(struct squashfs_dir_inode_header));\
463 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
464 	SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
465 	SQUASHFS_SWAP((s)->offset, d, 147, 13);\
466 	SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
467 	SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
468 }
469 
470 #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
471 	SQUASHFS_SWAP_START\
472 	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
473 			sizeof(struct squashfs_ldir_inode_header));\
474 	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
475 	SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
476 	SQUASHFS_SWAP((s)->offset, d, 155, 13);\
477 	SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
478 	SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
479 	SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
480 }
481 
482 #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
483 	SQUASHFS_SWAP_START\
484 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
485 	SQUASHFS_SWAP((s)->index, d, 0, 32);\
486 	SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
487 	SQUASHFS_SWAP((s)->size, d, 64, 8);\
488 }
489 
490 #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
491 	SQUASHFS_SWAP_START\
492 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
493 	SQUASHFS_SWAP((s)->count, d, 0, 8);\
494 	SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
495 	SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
496 }
497 
498 #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
499 	SQUASHFS_SWAP_START\
500 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
501 	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
502 	SQUASHFS_SWAP((s)->type, d, 13, 3);\
503 	SQUASHFS_SWAP((s)->size, d, 16, 8);\
504 	SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
505 }
506 
507 #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
508 	SQUASHFS_SWAP_START\
509 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
510 	SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
511 	SQUASHFS_SWAP((s)->size, d, 64, 32);\
512 }
513 
514 #define SQUASHFS_SWAP_SHORTS(s, d, n) {\
515 	int entry;\
516 	int bit_position;\
517 	SQUASHFS_SWAP_START\
518 	SQUASHFS_MEMSET(s, d, n * 2);\
519 	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
520 			16)\
521 		SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
522 }
523 
524 #define SQUASHFS_SWAP_INTS(s, d, n) {\
525 	int entry;\
526 	int bit_position;\
527 	SQUASHFS_SWAP_START\
528 	SQUASHFS_MEMSET(s, d, n * 4);\
529 	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
530 			32)\
531 		SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
532 }
533 
534 #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
535 	int entry;\
536 	int bit_position;\
537 	SQUASHFS_SWAP_START\
538 	SQUASHFS_MEMSET(s, d, n * 8);\
539 	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
540 			64)\
541 		SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
542 }
543 
544 #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
545 	int entry;\
546 	int bit_position;\
547 	SQUASHFS_SWAP_START\
548 	SQUASHFS_MEMSET(s, d, n * bits / 8);\
549 	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
550 			bits)\
551 		SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
552 }
553 
554 #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
555 
556 #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
557 
558 struct squashfs_base_inode_header_1 {
559 	unsigned int		inode_type:4;
560 	unsigned int		mode:12; /* protection */
561 	unsigned int		uid:4; /* index into uid table */
562 	unsigned int		guid:4; /* index into guid table */
563 } __attribute__ ((packed));
564 
565 struct squashfs_ipc_inode_header_1 {
566 	unsigned int		inode_type:4;
567 	unsigned int		mode:12; /* protection */
568 	unsigned int		uid:4; /* index into uid table */
569 	unsigned int		guid:4; /* index into guid table */
570 	unsigned int		type:4;
571 	unsigned int		offset:4;
572 } __attribute__ ((packed));
573 
574 struct squashfs_dev_inode_header_1 {
575 	unsigned int		inode_type:4;
576 	unsigned int		mode:12; /* protection */
577 	unsigned int		uid:4; /* index into uid table */
578 	unsigned int		guid:4; /* index into guid table */
579 	unsigned short		rdev;
580 } __attribute__ ((packed));
581 
582 struct squashfs_symlink_inode_header_1 {
583 	unsigned int		inode_type:4;
584 	unsigned int		mode:12; /* protection */
585 	unsigned int		uid:4; /* index into uid table */
586 	unsigned int		guid:4; /* index into guid table */
587 	unsigned short		symlink_size;
588 	char			symlink[0];
589 } __attribute__ ((packed));
590 
591 struct squashfs_reg_inode_header_1 {
592 	unsigned int		inode_type:4;
593 	unsigned int		mode:12; /* protection */
594 	unsigned int		uid:4; /* index into uid table */
595 	unsigned int		guid:4; /* index into guid table */
596 	unsigned int		mtime;
597 	unsigned int		start_block;
598 	unsigned int		file_size:32;
599 	unsigned short		block_list[0];
600 } __attribute__ ((packed));
601 
602 struct squashfs_dir_inode_header_1 {
603 	unsigned int		inode_type:4;
604 	unsigned int		mode:12; /* protection */
605 	unsigned int		uid:4; /* index into uid table */
606 	unsigned int		guid:4; /* index into guid table */
607 	unsigned int		file_size:19;
608 	unsigned int		offset:13;
609 	unsigned int		mtime;
610 	unsigned int		start_block:24;
611 } __attribute__  ((packed));
612 
613 #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
614 	SQUASHFS_MEMSET(s, d, n);\
615 	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
616 	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
617 	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
618 	SQUASHFS_SWAP((s)->guid, d, 20, 4);
619 
620 #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
621 	SQUASHFS_SWAP_START\
622 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
623 }
624 
625 #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
626 	SQUASHFS_SWAP_START\
627 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
628 			sizeof(struct squashfs_ipc_inode_header_1));\
629 	SQUASHFS_SWAP((s)->type, d, 24, 4);\
630 	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
631 }
632 
633 #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
634 	SQUASHFS_SWAP_START\
635 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
636 			sizeof(struct squashfs_dev_inode_header_1));\
637 	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
638 }
639 
640 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
641 	SQUASHFS_SWAP_START\
642 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
643 			sizeof(struct squashfs_symlink_inode_header_1));\
644 	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
645 }
646 
647 #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
648 	SQUASHFS_SWAP_START\
649 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
650 			sizeof(struct squashfs_reg_inode_header_1));\
651 	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
652 	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
653 	SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
654 }
655 
656 #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
657 	SQUASHFS_SWAP_START\
658 	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
659 			sizeof(struct squashfs_dir_inode_header_1));\
660 	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
661 	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
662 	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
663 	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
664 }
665 
666 #endif
667 
668 #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
669 
670 struct squashfs_dir_index_2 {
671 	unsigned int		index:27;
672 	unsigned int		start_block:29;
673 	unsigned char		size;
674 	unsigned char		name[0];
675 } __attribute__ ((packed));
676 
677 struct squashfs_base_inode_header_2 {
678 	unsigned int		inode_type:4;
679 	unsigned int		mode:12; /* protection */
680 	unsigned int		uid:8; /* index into uid table */
681 	unsigned int		guid:8; /* index into guid table */
682 } __attribute__ ((packed));
683 
684 struct squashfs_ipc_inode_header_2 {
685 	unsigned int		inode_type:4;
686 	unsigned int		mode:12; /* protection */
687 	unsigned int		uid:8; /* index into uid table */
688 	unsigned int		guid:8; /* index into guid table */
689 } __attribute__ ((packed));
690 
691 struct squashfs_dev_inode_header_2 {
692 	unsigned int		inode_type:4;
693 	unsigned int		mode:12; /* protection */
694 	unsigned int		uid:8; /* index into uid table */
695 	unsigned int		guid:8; /* index into guid table */
696 	unsigned short		rdev;
697 } __attribute__ ((packed));
698 
699 struct squashfs_symlink_inode_header_2 {
700 	unsigned int		inode_type:4;
701 	unsigned int		mode:12; /* protection */
702 	unsigned int		uid:8; /* index into uid table */
703 	unsigned int		guid:8; /* index into guid table */
704 	unsigned short		symlink_size;
705 	char			symlink[0];
706 } __attribute__ ((packed));
707 
708 struct squashfs_reg_inode_header_2 {
709 	unsigned int		inode_type:4;
710 	unsigned int		mode:12; /* protection */
711 	unsigned int		uid:8; /* index into uid table */
712 	unsigned int		guid:8; /* index into guid table */
713 	unsigned int		mtime;
714 	unsigned int		start_block;
715 	unsigned int		fragment;
716 	unsigned int		offset;
717 	unsigned int		file_size:32;
718 	unsigned short		block_list[0];
719 } __attribute__ ((packed));
720 
721 struct squashfs_dir_inode_header_2 {
722 	unsigned int		inode_type:4;
723 	unsigned int		mode:12; /* protection */
724 	unsigned int		uid:8; /* index into uid table */
725 	unsigned int		guid:8; /* index into guid table */
726 	unsigned int		file_size:19;
727 	unsigned int		offset:13;
728 	unsigned int		mtime;
729 	unsigned int		start_block:24;
730 } __attribute__  ((packed));
731 
732 struct squashfs_ldir_inode_header_2 {
733 	unsigned int		inode_type:4;
734 	unsigned int		mode:12; /* protection */
735 	unsigned int		uid:8; /* index into uid table */
736 	unsigned int		guid:8; /* index into guid table */
737 	unsigned int		file_size:27;
738 	unsigned int		offset:13;
739 	unsigned int		mtime;
740 	unsigned int		start_block:24;
741 	unsigned int		i_count:16;
742 	struct squashfs_dir_index_2	index[0];
743 } __attribute__  ((packed));
744 
745 union squashfs_inode_header_2 {
746 	struct squashfs_base_inode_header_2	base;
747 	struct squashfs_dev_inode_header_2	dev;
748 	struct squashfs_symlink_inode_header_2	symlink;
749 	struct squashfs_reg_inode_header_2	reg;
750 	struct squashfs_dir_inode_header_2	dir;
751 	struct squashfs_ldir_inode_header_2	ldir;
752 	struct squashfs_ipc_inode_header_2	ipc;
753 };
754 
755 struct squashfs_dir_header_2 {
756 	unsigned int		count:8;
757 	unsigned int		start_block:24;
758 } __attribute__ ((packed));
759 
760 struct squashfs_dir_entry_2 {
761 	unsigned int		offset:13;
762 	unsigned int		type:3;
763 	unsigned int		size:8;
764 	char			name[0];
765 } __attribute__ ((packed));
766 
767 struct squashfs_fragment_entry_2 {
768 	unsigned int		start_block;
769 	unsigned int		size;
770 } __attribute__ ((packed));
771 
772 #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
773 	SQUASHFS_MEMSET(s, d, n);\
774 	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
775 	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
776 	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
777 	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
778 
779 #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
780 	SQUASHFS_SWAP_START\
781 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
782 }
783 
784 #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
785 	SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
786 
787 #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
788 	SQUASHFS_SWAP_START\
789 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
790 			sizeof(struct squashfs_dev_inode_header_2)); \
791 	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
792 }
793 
794 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
795 	SQUASHFS_SWAP_START\
796 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
797 			sizeof(struct squashfs_symlink_inode_header_2));\
798 	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
799 }
800 
801 #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
802 	SQUASHFS_SWAP_START\
803 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
804 			sizeof(struct squashfs_reg_inode_header_2));\
805 	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
806 	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
807 	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
808 	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
809 	SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
810 }
811 
812 #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
813 	SQUASHFS_SWAP_START\
814 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
815 			sizeof(struct squashfs_dir_inode_header_2));\
816 	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
817 	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
818 	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
819 	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
820 }
821 
822 #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
823 	SQUASHFS_SWAP_START\
824 	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
825 			sizeof(struct squashfs_ldir_inode_header_2));\
826 	SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
827 	SQUASHFS_SWAP((s)->offset, d, 59, 13);\
828 	SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
829 	SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
830 	SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
831 }
832 
833 #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
834 	SQUASHFS_SWAP_START\
835 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
836 	SQUASHFS_SWAP((s)->index, d, 0, 27);\
837 	SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
838 	SQUASHFS_SWAP((s)->size, d, 56, 8);\
839 }
840 #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
841 	SQUASHFS_SWAP_START\
842 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
843 	SQUASHFS_SWAP((s)->count, d, 0, 8);\
844 	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
845 }
846 
847 #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
848 	SQUASHFS_SWAP_START\
849 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
850 	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
851 	SQUASHFS_SWAP((s)->type, d, 13, 3);\
852 	SQUASHFS_SWAP((s)->size, d, 16, 8);\
853 }
854 
855 #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
856 	SQUASHFS_SWAP_START\
857 	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
858 	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
859 	SQUASHFS_SWAP((s)->size, d, 32, 32);\
860 }
861 
862 #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
863 
864 /* fragment and fragment table defines */
865 #define SQUASHFS_FRAGMENT_BYTES_2(A)	(A * sizeof(struct squashfs_fragment_entry_2))
866 
867 #define SQUASHFS_FRAGMENT_INDEX_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) / \
868 					SQUASHFS_METADATA_SIZE)
869 
870 #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) % \
871 						SQUASHFS_METADATA_SIZE)
872 
873 #define SQUASHFS_FRAGMENT_INDEXES_2(A)	((SQUASHFS_FRAGMENT_BYTES_2(A) + \
874 					SQUASHFS_METADATA_SIZE - 1) / \
875 					SQUASHFS_METADATA_SIZE)
876 
877 #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)	(SQUASHFS_FRAGMENT_INDEXES_2(A) *\
878 						sizeof(int))
879 
880 #endif
881 
882 #ifdef __KERNEL__
883 
884 /*
885  * macros used to swap each structure entry, taking into account
886  * bitfields and different bitfield placing conventions on differing
887  * architectures
888  */
889 
890 #include <asm/byteorder.h>
891 
892 #ifdef __BIG_ENDIAN
893 	/* convert from little endian to big endian */
894 #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
895 		tbits, b_pos)
896 #else
897 	/* convert from big endian to little endian */
898 #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
899 		tbits, 64 - tbits - b_pos)
900 #endif
901 
902 #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
903 	b_pos = pos % 8;\
904 	val = 0;\
905 	s = (unsigned char *)p + (pos / 8);\
906 	d = ((unsigned char *) &val) + 7;\
907 	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
908 		*d-- = *s++;\
909 	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
910 }
911 
912 #define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
913 
914 #endif
915 #endif
916