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