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