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