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