squashfs_fs.h revision 1b899fc316f7eba7a31da12dc0c9b69ada441059
1#ifndef SQUASHFS_FS
2#define SQUASHFS_FS
3/*
4 * Squashfs
5 *
6 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
7 * Phillip Lougher <phillip@lougher.demon.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2,
12 * or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 * squashfs_fs.h
24 */
25
26#if 0
27#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
28#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
29#endif
30#endif
31
32#define SQUASHFS_CACHED_FRAGMENTS	CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
33#define SQUASHFS_MAJOR			4
34#define SQUASHFS_MINOR			0
35#define SQUASHFS_MAGIC			0x73717368
36#define SQUASHFS_MAGIC_SWAP		0x68737173
37#define SQUASHFS_START			0
38
39/* size of metadata (inode and directory) blocks */
40#define SQUASHFS_METADATA_SIZE		8192
41#define SQUASHFS_METADATA_LOG		13
42
43/* default size of data blocks */
44#define SQUASHFS_FILE_SIZE		131072
45#define SQUASHFS_FILE_LOG		17
46
47#define SQUASHFS_FILE_MAX_SIZE		1048576
48
49/* Max number of uids and gids */
50#define SQUASHFS_IDS			65536
51
52/* Max length of filename (not 255) */
53#define SQUASHFS_NAME_LEN		256
54
55#define SQUASHFS_INVALID		((long long) 0xffffffffffff)
56#define SQUASHFS_INVALID_FRAG		((unsigned int) 0xffffffff)
57#define SQUASHFS_INVALID_BLK		((long long) -1)
58#define SQUASHFS_USED_BLK		((long long) -2)
59
60/* Filesystem flags */
61#define SQUASHFS_NOI			0
62#define SQUASHFS_NOD			1
63#define SQUASHFS_CHECK			2
64#define SQUASHFS_NOF			3
65#define SQUASHFS_NO_FRAG		4
66#define SQUASHFS_ALWAYS_FRAG		5
67#define SQUASHFS_DUPLICATE		6
68#define SQUASHFS_EXPORT			7
69
70#define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
71
72#define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, \
73						SQUASHFS_NOI)
74
75#define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, \
76						SQUASHFS_NOD)
77
78#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
79						SQUASHFS_NOF)
80
81#define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, \
82						SQUASHFS_NO_FRAG)
83
84#define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
85						SQUASHFS_ALWAYS_FRAG)
86
87#define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, \
88						SQUASHFS_DUPLICATE)
89
90#define SQUASHFS_EXPORTABLE(flags)		SQUASHFS_BIT(flags, \
91						SQUASHFS_EXPORT)
92
93#define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, \
94						SQUASHFS_CHECK)
95
96#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
97		duplicate_checking, exportable)	(noi | (nod << 1) | (check_data << 2) \
98		| (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
99		(duplicate_checking << 6) | (exportable << 7))
100
101/* Max number of types and file types */
102#define SQUASHFS_DIR_TYPE		1
103#define SQUASHFS_FILE_TYPE		2
104#define SQUASHFS_SYMLINK_TYPE		3
105#define SQUASHFS_BLKDEV_TYPE		4
106#define SQUASHFS_CHRDEV_TYPE		5
107#define SQUASHFS_FIFO_TYPE		6
108#define SQUASHFS_SOCKET_TYPE		7
109#define SQUASHFS_LDIR_TYPE		8
110#define SQUASHFS_LREG_TYPE		9
111
112/* 1.0 filesystem type definitions */
113#define SQUASHFS_TYPES			5
114#define SQUASHFS_IPC_TYPE		0
115
116/* Flag whether block is compressed or uncompressed, bit is set if block is
117 * uncompressed */
118#define SQUASHFS_COMPRESSED_BIT		(1 << 15)
119
120#define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
121		(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
122
123#define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
124
125#define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
126
127#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	((B) & \
128	~SQUASHFS_COMPRESSED_BIT_BLOCK)
129
130#define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
131
132/*
133 * Inode number ops.  Inodes consist of a compressed block number, and an
134 * uncompressed  offset within that block
135 */
136#define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
137
138#define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
139
140#define SQUASHFS_MKINODE(A, B)		((squashfs_inode_t)(((squashfs_inode_t) (A)\
141					<< 16) + (B)))
142
143/* Compute 32 bit VFS inode number from squashfs inode number */
144#define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + \
145					((b) >> 2) + 1))
146/* XXX */
147
148/* Translate between VFS mode and squashfs mode */
149#define SQUASHFS_MODE(a)		((a) & 0xfff)
150
151/* fragment and fragment table defines */
152#define SQUASHFS_FRAGMENT_BYTES(A)	((A) * sizeof(struct squashfs_fragment_entry))
153
154#define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / \
155					SQUASHFS_METADATA_SIZE)
156
157#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % \
158						SQUASHFS_METADATA_SIZE)
159
160#define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + \
161					SQUASHFS_METADATA_SIZE - 1) / \
162					SQUASHFS_METADATA_SIZE)
163
164#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) *\
165						sizeof(long long))
166
167/* inode lookup table defines */
168#define SQUASHFS_LOOKUP_BYTES(A)	((A) * sizeof(squashfs_inode_t))
169
170#define SQUASHFS_LOOKUP_BLOCK(A)		(SQUASHFS_LOOKUP_BYTES(A) / \
171						SQUASHFS_METADATA_SIZE)
172
173#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)		(SQUASHFS_LOOKUP_BYTES(A) % \
174						SQUASHFS_METADATA_SIZE)
175
176#define SQUASHFS_LOOKUP_BLOCKS(A)	((SQUASHFS_LOOKUP_BYTES(A) + \
177					SQUASHFS_METADATA_SIZE - 1) / \
178					SQUASHFS_METADATA_SIZE)
179
180#define SQUASHFS_LOOKUP_BLOCK_BYTES(A)	(SQUASHFS_LOOKUP_BLOCKS(A) *\
181					sizeof(long long))
182
183/* uid lookup table defines */
184#define SQUASHFS_ID_BYTES(A)	((A) * sizeof(unsigned int))
185
186#define SQUASHFS_ID_BLOCK(A)		(SQUASHFS_ID_BYTES(A) / \
187						SQUASHFS_METADATA_SIZE)
188
189#define SQUASHFS_ID_BLOCK_OFFSET(A)		(SQUASHFS_ID_BYTES(A) % \
190						SQUASHFS_METADATA_SIZE)
191
192#define SQUASHFS_ID_BLOCKS(A)	((SQUASHFS_ID_BYTES(A) + \
193					SQUASHFS_METADATA_SIZE - 1) / \
194					SQUASHFS_METADATA_SIZE)
195
196#define SQUASHFS_ID_BLOCK_BYTES(A)	(SQUASHFS_ID_BLOCKS(A) *\
197					sizeof(long long))
198
199/* cached data constants for filesystem */
200#define SQUASHFS_CACHED_BLKS		8
201
202#define SQUASHFS_MAX_FILE_SIZE_LOG	64
203
204#define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << \
205					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
206
207#define SQUASHFS_MARKER_BYTE		0xff
208
209/* meta index cache */
210#define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
211#define SQUASHFS_META_ENTRIES	31
212#define SQUASHFS_META_NUMBER	8
213#define SQUASHFS_SLOTS		4
214
215struct meta_entry {
216	long long		data_block;
217	unsigned int		index_block;
218	unsigned short		offset;
219	unsigned short		pad;
220};
221
222struct meta_index {
223	unsigned int		inode_number;
224	unsigned int		offset;
225	unsigned short		entries;
226	unsigned short		skip;
227	unsigned short		locked;
228	unsigned short		pad;
229	struct meta_entry	meta_entry[SQUASHFS_META_ENTRIES];
230};
231
232
233/*
234 * definitions for structures on disk
235 */
236
237typedef long long		squashfs_block_t;
238typedef long long		squashfs_inode_t;
239
240#define COMPRESSION_ZLIB 1
241
242struct squashfs_super_block {
243	unsigned int		s_magic;
244	unsigned int		inodes;
245	unsigned int		mkfs_time /* time of filesystem creation */;
246	unsigned int		block_size;
247	unsigned int		fragments;
248	unsigned short		compression;
249	unsigned short		block_log;
250	unsigned short		flags;
251	unsigned short		no_ids;
252	unsigned short		s_major;
253	unsigned short		s_minor;
254	squashfs_inode_t	root_inode;
255	long long		bytes_used;
256	long long		id_table_start;
257	long long		xattr_table_start;
258	long long		inode_table_start;
259	long long		directory_table_start;
260	long long		fragment_table_start;
261	long long		lookup_table_start;
262};
263
264struct squashfs_dir_index {
265	unsigned int		index;
266	unsigned int		start_block;
267	unsigned int		size;
268	unsigned char		name[0];
269};
270
271#define SQUASHFS_BASE_INODE_HEADER		\
272	unsigned short		inode_type;	\
273	unsigned short		mode;	\
274	unsigned short		uid;		\
275	unsigned short		guid;		\
276	unsigned int		mtime;		\
277	unsigned int 		inode_number;
278
279struct squashfs_base_inode_header {
280	SQUASHFS_BASE_INODE_HEADER;
281};
282
283struct squashfs_ipc_inode_header {
284	SQUASHFS_BASE_INODE_HEADER;
285	unsigned int		nlink;
286};
287
288struct squashfs_dev_inode_header {
289	SQUASHFS_BASE_INODE_HEADER;
290	unsigned int		nlink;
291	unsigned int		rdev;
292};
293
294struct squashfs_symlink_inode_header {
295	SQUASHFS_BASE_INODE_HEADER;
296	unsigned int		nlink;
297	unsigned int		symlink_size;
298	char			symlink[0];
299};
300
301struct squashfs_reg_inode_header {
302	SQUASHFS_BASE_INODE_HEADER;
303	unsigned int		start_block;
304	unsigned int		fragment;
305	unsigned int		offset;
306	unsigned int		file_size;
307	unsigned short		block_list[0];
308};
309
310struct squashfs_lreg_inode_header {
311	SQUASHFS_BASE_INODE_HEADER;
312	squashfs_block_t	start_block;
313	long long		file_size;
314	long long		sparse;
315	unsigned int		nlink;
316	unsigned int		fragment;
317	unsigned int		offset;
318	unsigned int		xattr;
319	unsigned short		block_list[0];
320};
321
322struct squashfs_dir_inode_header {
323	SQUASHFS_BASE_INODE_HEADER;
324	unsigned int		start_block;
325	unsigned int		nlink;
326	unsigned short		file_size;
327	unsigned short		offset;
328	unsigned int		parent_inode;
329};
330
331struct squashfs_ldir_inode_header {
332	SQUASHFS_BASE_INODE_HEADER;
333	unsigned int		nlink;
334	unsigned int		file_size;
335	unsigned int		start_block;
336	unsigned int		parent_inode;
337	unsigned short		i_count;
338	unsigned short		offset;
339	struct squashfs_dir_index	index[0];
340};
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 short		offset;
355	short			inode_number;
356	unsigned short		type;
357	unsigned short		size;
358	char			name[0];
359};
360
361struct squashfs_dir_header {
362	unsigned int		count;
363	unsigned int		start_block;
364	unsigned int		inode_number;
365};
366
367struct squashfs_fragment_entry {
368	long long		start_block;
369	unsigned int		size;
370	unsigned int		unused;
371};
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#define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
580
581#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
582
583struct squashfs_base_inode_header_1 {
584	unsigned int		inode_type:4;
585	unsigned int		mode:12; /* protection */
586	unsigned int		uid:4; /* index into uid table */
587	unsigned int		guid:4; /* index into guid table */
588} __attribute__ ((packed));
589
590struct squashfs_ipc_inode_header_1 {
591	unsigned int		inode_type:4;
592	unsigned int		mode:12; /* protection */
593	unsigned int		uid:4; /* index into uid table */
594	unsigned int		guid:4; /* index into guid table */
595	unsigned int		type:4;
596	unsigned int		offset:4;
597} __attribute__ ((packed));
598
599struct squashfs_dev_inode_header_1 {
600	unsigned int		inode_type:4;
601	unsigned int		mode:12; /* protection */
602	unsigned int		uid:4; /* index into uid table */
603	unsigned int		guid:4; /* index into guid table */
604	unsigned short		rdev;
605} __attribute__ ((packed));
606
607struct squashfs_symlink_inode_header_1 {
608	unsigned int		inode_type:4;
609	unsigned int		mode:12; /* protection */
610	unsigned int		uid:4; /* index into uid table */
611	unsigned int		guid:4; /* index into guid table */
612	unsigned short		symlink_size;
613	char			symlink[0];
614} __attribute__ ((packed));
615
616struct squashfs_reg_inode_header_1 {
617	unsigned int		inode_type:4;
618	unsigned int		mode:12; /* protection */
619	unsigned int		uid:4; /* index into uid table */
620	unsigned int		guid:4; /* index into guid table */
621	unsigned int		mtime;
622	unsigned int		start_block;
623	unsigned int		file_size:32;
624	unsigned short		block_list[0];
625} __attribute__ ((packed));
626
627struct squashfs_dir_inode_header_1 {
628	unsigned int		inode_type:4;
629	unsigned int		mode:12; /* protection */
630	unsigned int		uid:4; /* index into uid table */
631	unsigned int		guid:4; /* index into guid table */
632	unsigned int		file_size:19;
633	unsigned int		offset:13;
634	unsigned int		mtime;
635	unsigned int		start_block:24;
636} __attribute__  ((packed));
637
638union squashfs_inode_header_1 {
639	struct squashfs_base_inode_header_1	base;
640	struct squashfs_dev_inode_header_1	dev;
641	struct squashfs_symlink_inode_header_1	symlink;
642	struct squashfs_reg_inode_header_1	reg;
643	struct squashfs_dir_inode_header_1	dir;
644	struct squashfs_ipc_inode_header_1	ipc;
645};
646
647#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
648	SQUASHFS_MEMSET(s, d, n);\
649	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
650	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
651	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
652	SQUASHFS_SWAP((s)->guid, d, 20, 4);
653
654#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
655	SQUASHFS_SWAP_START\
656	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
657}
658
659#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
660	SQUASHFS_SWAP_START\
661	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
662			sizeof(struct squashfs_ipc_inode_header_1));\
663	SQUASHFS_SWAP((s)->type, d, 24, 4);\
664	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
665}
666
667#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
668	SQUASHFS_SWAP_START\
669	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
670			sizeof(struct squashfs_dev_inode_header_1));\
671	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
672}
673
674#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
675	SQUASHFS_SWAP_START\
676	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
677			sizeof(struct squashfs_symlink_inode_header_1));\
678	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
679}
680
681#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
682	SQUASHFS_SWAP_START\
683	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
684			sizeof(struct squashfs_reg_inode_header_1));\
685	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
686	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
687	SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
688}
689
690#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
691	SQUASHFS_SWAP_START\
692	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
693			sizeof(struct squashfs_dir_inode_header_1));\
694	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
695	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
696	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
697	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
698}
699
700#endif
701
702#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
703
704struct squashfs_dir_index_2 {
705	unsigned int		index:27;
706	unsigned int		start_block:29;
707	unsigned char		size;
708	unsigned char		name[0];
709} __attribute__ ((packed));
710
711struct squashfs_base_inode_header_2 {
712	unsigned int		inode_type:4;
713	unsigned int		mode:12; /* protection */
714	unsigned int		uid:8; /* index into uid table */
715	unsigned int		guid:8; /* index into guid table */
716} __attribute__ ((packed));
717
718struct squashfs_ipc_inode_header_2 {
719	unsigned int		inode_type:4;
720	unsigned int		mode:12; /* protection */
721	unsigned int		uid:8; /* index into uid table */
722	unsigned int		guid:8; /* index into guid table */
723} __attribute__ ((packed));
724
725struct squashfs_dev_inode_header_2 {
726	unsigned int		inode_type:4;
727	unsigned int		mode:12; /* protection */
728	unsigned int		uid:8; /* index into uid table */
729	unsigned int		guid:8; /* index into guid table */
730	unsigned short		rdev;
731} __attribute__ ((packed));
732
733struct squashfs_symlink_inode_header_2 {
734	unsigned int		inode_type:4;
735	unsigned int		mode:12; /* protection */
736	unsigned int		uid:8; /* index into uid table */
737	unsigned int		guid:8; /* index into guid table */
738	unsigned short		symlink_size;
739	char			symlink[0];
740} __attribute__ ((packed));
741
742struct squashfs_reg_inode_header_2 {
743	unsigned int		inode_type:4;
744	unsigned int		mode:12; /* protection */
745	unsigned int		uid:8; /* index into uid table */
746	unsigned int		guid:8; /* index into guid table */
747	unsigned int		mtime;
748	unsigned int		start_block;
749	unsigned int		fragment;
750	unsigned int		offset;
751	unsigned int		file_size:32;
752	unsigned short		block_list[0];
753} __attribute__ ((packed));
754
755struct squashfs_dir_inode_header_2 {
756	unsigned int		inode_type:4;
757	unsigned int		mode:12; /* protection */
758	unsigned int		uid:8; /* index into uid table */
759	unsigned int		guid:8; /* index into guid table */
760	unsigned int		file_size:19;
761	unsigned int		offset:13;
762	unsigned int		mtime;
763	unsigned int		start_block:24;
764} __attribute__  ((packed));
765
766struct squashfs_ldir_inode_header_2 {
767	unsigned int		inode_type:4;
768	unsigned int		mode:12; /* protection */
769	unsigned int		uid:8; /* index into uid table */
770	unsigned int		guid:8; /* index into guid table */
771	unsigned int		file_size:27;
772	unsigned int		offset:13;
773	unsigned int		mtime;
774	unsigned int		start_block:24;
775	unsigned int		i_count:16;
776	struct squashfs_dir_index_2	index[0];
777} __attribute__  ((packed));
778
779union squashfs_inode_header_2 {
780	struct squashfs_base_inode_header_2	base;
781	struct squashfs_dev_inode_header_2	dev;
782	struct squashfs_symlink_inode_header_2	symlink;
783	struct squashfs_reg_inode_header_2	reg;
784	struct squashfs_dir_inode_header_2	dir;
785	struct squashfs_ldir_inode_header_2	ldir;
786	struct squashfs_ipc_inode_header_2	ipc;
787};
788
789struct squashfs_dir_header_2 {
790	unsigned int		count:8;
791	unsigned int		start_block:24;
792} __attribute__ ((packed));
793
794struct squashfs_dir_entry_2 {
795	unsigned int		offset:13;
796	unsigned int		type:3;
797	unsigned int		size:8;
798	char			name[0];
799} __attribute__ ((packed));
800
801struct squashfs_fragment_entry_2 {
802	unsigned int		start_block;
803	unsigned int		size;
804} __attribute__ ((packed));
805
806#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
807	SQUASHFS_MEMSET(s, d, n);\
808	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
809	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
810	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
811	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
812
813#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
814	SQUASHFS_SWAP_START\
815	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
816}
817
818#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
819	SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
820
821#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
822	SQUASHFS_SWAP_START\
823	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
824			sizeof(struct squashfs_dev_inode_header_2)); \
825	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
826}
827
828#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
829	SQUASHFS_SWAP_START\
830	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
831			sizeof(struct squashfs_symlink_inode_header_2));\
832	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
833}
834
835#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
836	SQUASHFS_SWAP_START\
837	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
838			sizeof(struct squashfs_reg_inode_header_2));\
839	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
840	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
841	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
842	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
843	SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
844}
845
846#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
847	SQUASHFS_SWAP_START\
848	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
849			sizeof(struct squashfs_dir_inode_header_2));\
850	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
851	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
852	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
853	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
854}
855
856#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
857	SQUASHFS_SWAP_START\
858	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
859			sizeof(struct squashfs_ldir_inode_header_2));\
860	SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
861	SQUASHFS_SWAP((s)->offset, d, 59, 13);\
862	SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
863	SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
864	SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
865}
866
867#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
868	SQUASHFS_SWAP_START\
869	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
870	SQUASHFS_SWAP((s)->index, d, 0, 27);\
871	SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
872	SQUASHFS_SWAP((s)->size, d, 56, 8);\
873}
874#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
875	SQUASHFS_SWAP_START\
876	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
877	SQUASHFS_SWAP((s)->count, d, 0, 8);\
878	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
879}
880
881#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
882	SQUASHFS_SWAP_START\
883	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
884	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
885	SQUASHFS_SWAP((s)->type, d, 13, 3);\
886	SQUASHFS_SWAP((s)->size, d, 16, 8);\
887}
888
889#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
890	SQUASHFS_SWAP_START\
891	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
892	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
893	SQUASHFS_SWAP((s)->size, d, 32, 32);\
894}
895
896#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
897
898/* fragment and fragment table defines */
899#define SQUASHFS_FRAGMENT_BYTES_2(A)	(A * sizeof(struct squashfs_fragment_entry_2))
900
901#define SQUASHFS_FRAGMENT_INDEX_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) / \
902					SQUASHFS_METADATA_SIZE)
903
904#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) % \
905						SQUASHFS_METADATA_SIZE)
906
907#define SQUASHFS_FRAGMENT_INDEXES_2(A)	((SQUASHFS_FRAGMENT_BYTES_2(A) + \
908					SQUASHFS_METADATA_SIZE - 1) / \
909					SQUASHFS_METADATA_SIZE)
910
911#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)	(SQUASHFS_FRAGMENT_INDEXES_2(A) *\
912						sizeof(int))
913
914#endif
915
916#ifdef __KERNEL__
917
918/*
919 * macros used to swap each structure entry, taking into account
920 * bitfields and different bitfield placing conventions on differing
921 * architectures
922 */
923
924#include <asm/byteorder.h>
925
926#ifdef __BIG_ENDIAN
927	/* convert from little endian to big endian */
928#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
929		tbits, b_pos)
930#else
931	/* convert from big endian to little endian */
932#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
933		tbits, 64 - tbits - b_pos)
934#endif
935
936#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
937	b_pos = pos % 8;\
938	val = 0;\
939	s = (unsigned char *)p + (pos / 8);\
940	d = ((unsigned char *) &val) + 7;\
941	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
942		*d-- = *s++;\
943	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
944}
945
946#define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
947
948#endif
949#endif
950