source:
clfs-embedded/patches/linux-2.6.20-squashfs-1.patch@
c273052
Last change on this file since c273052 was 5956516, checked in by , 18 years ago | |
---|---|
|
|
File size: 123.3 KB |
-
linux-2.6.19.
diff -Nru linux-2.6.19.ori2/fs/Kconfig linux-2.6.19.ori/fs/Kconfig
old new 1407 1407 1408 1408 If unsure, say N. 1409 1409 1410 config SQUASHFS 1411 tristate "SquashFS 3.1 - Squashed file system support" 1412 select ZLIB_INFLATE 1413 help 1414 Saying Y here includes support for SquashFS 3.1 (a Compressed Read-Only File 1415 System). Squashfs is a highly compressed read-only filesystem for Linux. 1416 It uses zlib compression to compress both files, inodes and directories. 1417 Inodes in the system are very small and all blocks are packed to minimise 1418 data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. 1419 SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full 1420 uid/gid information, hard links and timestamps. 1421 1422 Squashfs is intended for general read-only filesystem use, for archival 1423 use (i.e. in cases where a .tar.gz file may be used), and in embedded 1424 systems where low overhead is needed. Further information and filesystem tools 1425 are available from http://squashfs.sourceforge.net. 1426 1427 If you want to compile this as a module ( = code which can be 1428 inserted in and removed from the running kernel whenever you want), 1429 say M here and read <file:Documentation/modules.txt>. The module 1430 will be called squashfs. Note that the root file system (the one 1431 containing the directory /) cannot be compiled as a module. 1432 1433 If unsure, say N. 1434 1435 config SQUASHFS_EMBEDDED 1436 1437 bool "Additional options for memory-constrained systems" 1438 depends on SQUASHFS 1439 default n 1440 help 1441 Saying Y here allows you to specify cache sizes and how Squashfs 1442 allocates memory. This is only intended for memory constrained 1443 systems. 1444 1445 If unsure, say N. 1446 1447 config SQUASHFS_FRAGMENT_CACHE_SIZE 1448 int "Number of fragments cached" if SQUASHFS_EMBEDDED 1449 depends on SQUASHFS 1450 default "3" 1451 help 1452 By default SquashFS caches the last 3 fragments read from 1453 the filesystem. Increasing this amount may mean SquashFS 1454 has to re-read fragments less often from disk, at the expense 1455 of extra system memory. Decreasing this amount will mean 1456 SquashFS uses less memory at the expense of extra reads from disk. 1457 1458 Note there must be at least one cached fragment. Anything 1459 much more than three will probably not make much difference. 1460 1461 config SQUASHFS_VMALLOC 1462 bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED 1463 depends on SQUASHFS 1464 default n 1465 help 1466 By default SquashFS uses kmalloc to obtain fragment cache memory. 1467 Kmalloc memory is the standard kernel allocator, but it can fail 1468 on memory constrained systems. Because of the way Vmalloc works, 1469 Vmalloc can succeed when kmalloc fails. Specifying this option 1470 will make SquashFS always use Vmalloc to allocate the 1471 fragment cache memory. 1472 1473 If unsure, say N. 1474 1410 1475 config VXFS_FS 1411 1476 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" 1412 1477 depends on BLOCK -
linux-2.6.19.
diff -Nru linux-2.6.19.ori2/fs/Makefile linux-2.6.19.ori/fs/Makefile
old new 67 67 obj-$(CONFIG_JBD2) += jbd2/ 68 68 obj-$(CONFIG_EXT2_FS) += ext2/ 69 69 obj-$(CONFIG_CRAMFS) += cramfs/ 70 obj-$(CONFIG_SQUASHFS) += squashfs/ 70 71 obj-$(CONFIG_RAMFS) += ramfs/ 71 72 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ 72 73 obj-$(CONFIG_CODA_FS) += coda/ -
fs/squashfs/Makefile
diff -Nru linux-2.6.19.ori2/fs/squashfs/Makefile linux-2.6.19.ori/fs/squashfs/Makefile
old new 1 # 2 # Makefile for the linux squashfs routines. 3 # 4 5 obj-$(CONFIG_SQUASHFS) += squashfs.o 6 squashfs-y += inode.o 7 squashfs-y += squashfs2_0.o -
fs/squashfs/inode.c
diff -Nru linux-2.6.19.ori2/fs/squashfs/inode.c linux-2.6.19.ori/fs/squashfs/inode.c
old new 1 /* 2 * Squashfs - a compressed read only filesystem for Linux 3 * 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006 5 * Phillip Lougher <phillip@lougher.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2, 10 * or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * 21 * inode.c 22 */ 23 24 #include <linux/types.h> 25 #include <linux/squashfs_fs.h> 26 #include <linux/module.h> 27 #include <linux/errno.h> 28 #include <linux/slab.h> 29 #include <linux/zlib.h> 30 #include <linux/fs.h> 31 #include <linux/smp_lock.h> 32 #include <linux/slab.h> 33 #include <linux/squashfs_fs_sb.h> 34 #include <linux/squashfs_fs_i.h> 35 #include <linux/buffer_head.h> 36 #include <linux/vfs.h> 37 #include <linux/init.h> 38 #include <linux/dcache.h> 39 #include <linux/wait.h> 40 #include <linux/blkdev.h> 41 #include <linux/vmalloc.h> 42 #include <asm/uaccess.h> 43 #include <asm/semaphore.h> 44 45 #include "squashfs.h" 46 47 static void squashfs_put_super(struct super_block *); 48 static int squashfs_statfs(struct dentry *, struct kstatfs *); 49 static int squashfs_symlink_readpage(struct file *file, struct page *page); 50 static int squashfs_readpage(struct file *file, struct page *page); 51 static int squashfs_readpage4K(struct file *file, struct page *page); 52 static int squashfs_readdir(struct file *, void *, filldir_t); 53 static struct inode *squashfs_alloc_inode(struct super_block *sb); 54 static void squashfs_destroy_inode(struct inode *inode); 55 static int init_inodecache(void); 56 static void destroy_inodecache(void); 57 static struct dentry *squashfs_lookup(struct inode *, struct dentry *, 58 struct nameidata *); 59 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode); 60 static long long read_blocklist(struct inode *inode, int index, 61 int readahead_blks, char *block_list, 62 unsigned short **block_p, unsigned int *bsize); 63 static int squashfs_get_sb(struct file_system_type *, int, const char *, void *, 64 struct vfsmount *); 65 66 static struct file_system_type squashfs_fs_type = { 67 .owner = THIS_MODULE, 68 .name = "squashfs", 69 .get_sb = squashfs_get_sb, 70 .kill_sb = kill_block_super, 71 .fs_flags = FS_REQUIRES_DEV 72 }; 73 74 static unsigned char squashfs_filetype_table[] = { 75 DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK 76 }; 77 78 static struct super_operations squashfs_ops = { 79 .alloc_inode = squashfs_alloc_inode, 80 .destroy_inode = squashfs_destroy_inode, 81 .statfs = squashfs_statfs, 82 .put_super = squashfs_put_super, 83 }; 84 85 SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { 86 .readpage = squashfs_symlink_readpage 87 }; 88 89 SQSH_EXTERN struct address_space_operations squashfs_aops = { 90 .readpage = squashfs_readpage 91 }; 92 93 SQSH_EXTERN struct address_space_operations squashfs_aops_4K = { 94 .readpage = squashfs_readpage4K 95 }; 96 97 static struct file_operations squashfs_dir_ops = { 98 .read = generic_read_dir, 99 .readdir = squashfs_readdir 100 }; 101 102 SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { 103 .lookup = squashfs_lookup 104 }; 105 106 107 static struct buffer_head *get_block_length(struct super_block *s, 108 int *cur_index, int *offset, int *c_byte) 109 { 110 struct squashfs_sb_info *msblk = s->s_fs_info; 111 unsigned short temp; 112 struct buffer_head *bh; 113 114 if (!(bh = sb_bread(s, *cur_index))) 115 goto out; 116 117 if (msblk->devblksize - *offset == 1) { 118 if (msblk->swap) 119 ((unsigned char *) &temp)[1] = *((unsigned char *) 120 (bh->b_data + *offset)); 121 else 122 ((unsigned char *) &temp)[0] = *((unsigned char *) 123 (bh->b_data + *offset)); 124 brelse(bh); 125 if (!(bh = sb_bread(s, ++(*cur_index)))) 126 goto out; 127 if (msblk->swap) 128 ((unsigned char *) &temp)[0] = *((unsigned char *) 129 bh->b_data); 130 else 131 ((unsigned char *) &temp)[1] = *((unsigned char *) 132 bh->b_data); 133 *c_byte = temp; 134 *offset = 1; 135 } else { 136 if (msblk->swap) { 137 ((unsigned char *) &temp)[1] = *((unsigned char *) 138 (bh->b_data + *offset)); 139 ((unsigned char *) &temp)[0] = *((unsigned char *) 140 (bh->b_data + *offset + 1)); 141 } else { 142 ((unsigned char *) &temp)[0] = *((unsigned char *) 143 (bh->b_data + *offset)); 144 ((unsigned char *) &temp)[1] = *((unsigned char *) 145 (bh->b_data + *offset + 1)); 146 } 147 *c_byte = temp; 148 *offset += 2; 149 } 150 151 if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { 152 if (*offset == msblk->devblksize) { 153 brelse(bh); 154 if (!(bh = sb_bread(s, ++(*cur_index)))) 155 goto out; 156 *offset = 0; 157 } 158 if (*((unsigned char *) (bh->b_data + *offset)) != 159 SQUASHFS_MARKER_BYTE) { 160 ERROR("Metadata block marker corrupt @ %x\n", 161 *cur_index); 162 brelse(bh); 163 goto out; 164 } 165 (*offset)++; 166 } 167 return bh; 168 169 out: 170 return NULL; 171 } 172 173 174 SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, 175 long long index, unsigned int length, 176 long long *next_index) 177 { 178 struct squashfs_sb_info *msblk = s->s_fs_info; 179 struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> 180 msblk->devblksize_log2) + 2]; 181 unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); 182 unsigned int cur_index = index >> msblk->devblksize_log2; 183 int bytes, avail_bytes, b = 0, k; 184 char *c_buffer; 185 unsigned int compressed; 186 unsigned int c_byte = length; 187 188 if (c_byte) { 189 bytes = msblk->devblksize - offset; 190 compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); 191 c_buffer = compressed ? msblk->read_data : buffer; 192 c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); 193 194 TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed 195 ? "" : "un", (unsigned int) c_byte); 196 197 if (!(bh[0] = sb_getblk(s, cur_index))) 198 goto block_release; 199 200 for (b = 1; bytes < c_byte; b++) { 201 if (!(bh[b] = sb_getblk(s, ++cur_index))) 202 goto block_release; 203 bytes += msblk->devblksize; 204 } 205 ll_rw_block(READ, b, bh); 206 } else { 207 if (!(bh[0] = get_block_length(s, &cur_index, &offset, 208 &c_byte))) 209 goto read_failure; 210 211 bytes = msblk->devblksize - offset; 212 compressed = SQUASHFS_COMPRESSED(c_byte); 213 c_buffer = compressed ? msblk->read_data : buffer; 214 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 215 216 TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed 217 ? "" : "un", (unsigned int) c_byte); 218 219 for (b = 1; bytes < c_byte; b++) { 220 if (!(bh[b] = sb_getblk(s, ++cur_index))) 221 goto block_release; 222 bytes += msblk->devblksize; 223 } 224 ll_rw_block(READ, b - 1, bh + 1); 225 } 226 227 if (compressed) 228 down(&msblk->read_data_mutex); 229 230 for (bytes = 0, k = 0; k < b; k++) { 231 avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? 232 msblk->devblksize - offset : 233 c_byte - bytes; 234 wait_on_buffer(bh[k]); 235 if (!buffer_uptodate(bh[k])) 236 goto block_release; 237 memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes); 238 bytes += avail_bytes; 239 offset = 0; 240 brelse(bh[k]); 241 } 242 243 /* 244 * uncompress block 245 */ 246 if (compressed) { 247 int zlib_err; 248 249 msblk->stream.next_in = c_buffer; 250 msblk->stream.avail_in = c_byte; 251 msblk->stream.next_out = buffer; 252 msblk->stream.avail_out = msblk->read_size; 253 254 if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || 255 ((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) 256 != Z_STREAM_END) || ((zlib_err = 257 zlib_inflateEnd(&msblk->stream)) != Z_OK)) { 258 ERROR("zlib_fs returned unexpected result 0x%x\n", 259 zlib_err); 260 bytes = 0; 261 } else 262 bytes = msblk->stream.total_out; 263 264 up(&msblk->read_data_mutex); 265 } 266 267 if (next_index) 268 *next_index = index + c_byte + (length ? 0 : 269 (SQUASHFS_CHECK_DATA(msblk->sblk.flags) 270 ? 3 : 2)); 271 return bytes; 272 273 block_release: 274 while (--b >= 0) 275 brelse(bh[b]); 276 277 read_failure: 278 ERROR("sb_bread failed reading block 0x%x\n", cur_index); 279 return 0; 280 } 281 282 283 SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer, 284 long long block, unsigned int offset, 285 int length, long long *next_block, 286 unsigned int *next_offset) 287 { 288 struct squashfs_sb_info *msblk = s->s_fs_info; 289 int n, i, bytes, return_length = length; 290 long long next_index; 291 292 TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); 293 294 while ( 1 ) { 295 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 296 if (msblk->block_cache[i].block == block) 297 break; 298 299 down(&msblk->block_cache_mutex); 300 301 if (i == SQUASHFS_CACHED_BLKS) { 302 /* read inode header block */ 303 for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS; 304 n ; n --, i = (i + 1) % 305 SQUASHFS_CACHED_BLKS) 306 if (msblk->block_cache[i].block != 307 SQUASHFS_USED_BLK) 308 break; 309 310 if (n == 0) { 311 wait_queue_t wait; 312 313 init_waitqueue_entry(&wait, current); 314 add_wait_queue(&msblk->waitq, &wait); 315 set_current_state(TASK_UNINTERRUPTIBLE); 316 up(&msblk->block_cache_mutex); 317 schedule(); 318 set_current_state(TASK_RUNNING); 319 remove_wait_queue(&msblk->waitq, &wait); 320 continue; 321 } 322 msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS; 323 324 if (msblk->block_cache[i].block == 325 SQUASHFS_INVALID_BLK) { 326 if (!(msblk->block_cache[i].data = 327 kmalloc(SQUASHFS_METADATA_SIZE, 328 GFP_KERNEL))) { 329 ERROR("Failed to allocate cache" 330 "block\n"); 331 up(&msblk->block_cache_mutex); 332 goto out; 333 } 334 } 335 336 msblk->block_cache[i].block = SQUASHFS_USED_BLK; 337 up(&msblk->block_cache_mutex); 338 339 if (!(msblk->block_cache[i].length = 340 squashfs_read_data(s, 341 msblk->block_cache[i].data, 342 block, 0, &next_index))) { 343 ERROR("Unable to read cache block [%llx:%x]\n", 344 block, offset); 345 goto out; 346 } 347 348 down(&msblk->block_cache_mutex); 349 wake_up(&msblk->waitq); 350 msblk->block_cache[i].block = block; 351 msblk->block_cache[i].next_index = next_index; 352 TRACE("Read cache block [%llx:%x]\n", block, offset); 353 } 354 355 if (msblk->block_cache[i].block != block) { 356 up(&msblk->block_cache_mutex); 357 continue; 358 } 359 360 if ((bytes = msblk->block_cache[i].length - offset) >= length) { 361 if (buffer) 362 memcpy(buffer, msblk->block_cache[i].data + 363 offset, length); 364 if (msblk->block_cache[i].length - offset == length) { 365 *next_block = msblk->block_cache[i].next_index; 366 *next_offset = 0; 367 } else { 368 *next_block = block; 369 *next_offset = offset + length; 370 } 371 up(&msblk->block_cache_mutex); 372 goto finish; 373 } else { 374 if (buffer) { 375 memcpy(buffer, msblk->block_cache[i].data + 376 offset, bytes); 377 buffer += bytes; 378 } 379 block = msblk->block_cache[i].next_index; 380 up(&msblk->block_cache_mutex); 381 length -= bytes; 382 offset = 0; 383 } 384 } 385 386 finish: 387 return return_length; 388 out: 389 return 0; 390 } 391 392 393 static int get_fragment_location(struct super_block *s, unsigned int fragment, 394 long long *fragment_start_block, 395 unsigned int *fragment_size) 396 { 397 struct squashfs_sb_info *msblk = s->s_fs_info; 398 long long start_block = 399 msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; 400 int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); 401 struct squashfs_fragment_entry fragment_entry; 402 403 if (msblk->swap) { 404 struct squashfs_fragment_entry sfragment_entry; 405 406 if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, 407 start_block, offset, 408 sizeof(sfragment_entry), &start_block, 409 &offset)) 410 goto out; 411 SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); 412 } else 413 if (!squashfs_get_cached_block(s, (char *) &fragment_entry, 414 start_block, offset, 415 sizeof(fragment_entry), &start_block, 416 &offset)) 417 goto out; 418 419 *fragment_start_block = fragment_entry.start_block; 420 *fragment_size = fragment_entry.size; 421 422 return 1; 423 424 out: 425 return 0; 426 } 427 428 429 SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct 430 squashfs_fragment_cache *fragment) 431 { 432 down(&msblk->fragment_mutex); 433 fragment->locked --; 434 wake_up(&msblk->fragment_wait_queue); 435 up(&msblk->fragment_mutex); 436 } 437 438 439 SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block 440 *s, long long start_block, 441 int length) 442 { 443 int i, n; 444 struct squashfs_sb_info *msblk = s->s_fs_info; 445 446 while ( 1 ) { 447 down(&msblk->fragment_mutex); 448 449 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && 450 msblk->fragment[i].block != start_block; i++); 451 452 if (i == SQUASHFS_CACHED_FRAGMENTS) { 453 for (i = msblk->next_fragment, n = 454 SQUASHFS_CACHED_FRAGMENTS; n && 455 msblk->fragment[i].locked; n--, i = (i + 1) % 456 SQUASHFS_CACHED_FRAGMENTS); 457 458 if (n == 0) { 459 wait_queue_t wait; 460 461 init_waitqueue_entry(&wait, current); 462 add_wait_queue(&msblk->fragment_wait_queue, 463 &wait); 464 set_current_state(TASK_UNINTERRUPTIBLE); 465 up(&msblk->fragment_mutex); 466 schedule(); 467 set_current_state(TASK_RUNNING); 468 remove_wait_queue(&msblk->fragment_wait_queue, 469 &wait); 470 continue; 471 } 472 msblk->next_fragment = (msblk->next_fragment + 1) % 473 SQUASHFS_CACHED_FRAGMENTS; 474 475 if (msblk->fragment[i].data == NULL) 476 if (!(msblk->fragment[i].data = SQUASHFS_ALLOC 477 (SQUASHFS_FILE_MAX_SIZE))) { 478 ERROR("Failed to allocate fragment " 479 "cache block\n"); 480 up(&msblk->fragment_mutex); 481 goto out; 482 } 483 484 msblk->fragment[i].block = SQUASHFS_INVALID_BLK; 485 msblk->fragment[i].locked = 1; 486 up(&msblk->fragment_mutex); 487 488 if (!(msblk->fragment[i].length = squashfs_read_data(s, 489 msblk->fragment[i].data, 490 start_block, length, NULL))) { 491 ERROR("Unable to read fragment cache block " 492 "[%llx]\n", start_block); 493 msblk->fragment[i].locked = 0; 494 goto out; 495 } 496 497 msblk->fragment[i].block = start_block; 498 TRACE("New fragment %d, start block %lld, locked %d\n", 499 i, msblk->fragment[i].block, 500 msblk->fragment[i].locked); 501 break; 502 } 503 504 msblk->fragment[i].locked++; 505 up(&msblk->fragment_mutex); 506 TRACE("Got fragment %d, start block %lld, locked %d\n", i, 507 msblk->fragment[i].block, 508 msblk->fragment[i].locked); 509 break; 510 } 511 512 return &msblk->fragment[i]; 513 514 out: 515 return NULL; 516 } 517 518 519 static struct inode *squashfs_new_inode(struct super_block *s, 520 struct squashfs_base_inode_header *inodeb) 521 { 522 struct squashfs_sb_info *msblk = s->s_fs_info; 523 struct inode *i = new_inode(s); 524 525 if (i) { 526 i->i_ino = inodeb->inode_number; 527 i->i_mtime.tv_sec = inodeb->mtime; 528 i->i_atime.tv_sec = inodeb->mtime; 529 i->i_ctime.tv_sec = inodeb->mtime; 530 i->i_uid = msblk->uid[inodeb->uid]; 531 i->i_mode = inodeb->mode; 532 i->i_size = 0; 533 if (inodeb->guid == SQUASHFS_GUIDS) 534 i->i_gid = i->i_uid; 535 else 536 i->i_gid = msblk->guid[inodeb->guid]; 537 } 538 539 return i; 540 } 541 542 543 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode) 544 { 545 struct inode *i; 546 struct squashfs_sb_info *msblk = s->s_fs_info; 547 struct squashfs_super_block *sblk = &msblk->sblk; 548 long long block = SQUASHFS_INODE_BLK(inode) + 549 sblk->inode_table_start; 550 unsigned int offset = SQUASHFS_INODE_OFFSET(inode); 551 long long next_block; 552 unsigned int next_offset; 553 union squashfs_inode_header id, sid; 554 struct squashfs_base_inode_header *inodeb = &id.base, 555 *sinodeb = &sid.base; 556 557 TRACE("Entered squashfs_iget\n"); 558 559 if (msblk->swap) { 560 if (!squashfs_get_cached_block(s, (char *) sinodeb, block, 561 offset, sizeof(*sinodeb), &next_block, 562 &next_offset)) 563 goto failed_read; 564 SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, 565 sizeof(*sinodeb)); 566 } else 567 if (!squashfs_get_cached_block(s, (char *) inodeb, block, 568 offset, sizeof(*inodeb), &next_block, 569 &next_offset)) 570 goto failed_read; 571 572 switch(inodeb->inode_type) { 573 case SQUASHFS_FILE_TYPE: { 574 unsigned int frag_size; 575 long long frag_blk; 576 struct squashfs_reg_inode_header *inodep = &id.reg; 577 struct squashfs_reg_inode_header *sinodep = &sid.reg; 578 579 if (msblk->swap) { 580 if (!squashfs_get_cached_block(s, (char *) 581 sinodep, block, offset, 582 sizeof(*sinodep), &next_block, 583 &next_offset)) 584 goto failed_read; 585 SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); 586 } else 587 if (!squashfs_get_cached_block(s, (char *) 588 inodep, block, offset, 589 sizeof(*inodep), &next_block, 590 &next_offset)) 591 goto failed_read; 592 593 frag_blk = SQUASHFS_INVALID_BLK; 594 if (inodep->fragment != SQUASHFS_INVALID_FRAG && 595 !get_fragment_location(s, 596 inodep->fragment, &frag_blk, &frag_size)) 597 goto failed_read; 598 599 if((i = squashfs_new_inode(s, inodeb)) == NULL) 600 goto failed_read1; 601 602 i->i_nlink = 1; 603 i->i_size = inodep->file_size; 604 i->i_fop = &generic_ro_fops; 605 i->i_mode |= S_IFREG; 606 i->i_blocks = ((i->i_size - 1) >> 9) + 1; 607 SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; 608 SQUASHFS_I(i)->u.s1.fragment_size = frag_size; 609 SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; 610 SQUASHFS_I(i)->start_block = inodep->start_block; 611 SQUASHFS_I(i)->u.s1.block_list_start = next_block; 612 SQUASHFS_I(i)->offset = next_offset; 613 if (sblk->block_size > 4096) 614 i->i_data.a_ops = &squashfs_aops; 615 else 616 i->i_data.a_ops = &squashfs_aops_4K; 617 618 TRACE("File inode %x:%x, start_block %llx, " 619 "block_list_start %llx, offset %x\n", 620 SQUASHFS_INODE_BLK(inode), offset, 621 inodep->start_block, next_block, 622 next_offset); 623 break; 624 } 625 case SQUASHFS_LREG_TYPE: { 626 unsigned int frag_size; 627 long long frag_blk; 628 struct squashfs_lreg_inode_header *inodep = &id.lreg; 629 struct squashfs_lreg_inode_header *sinodep = &sid.lreg; 630 631 if (msblk->swap) { 632 if (!squashfs_get_cached_block(s, (char *) 633 sinodep, block, offset, 634 sizeof(*sinodep), &next_block, 635 &next_offset)) 636 goto failed_read; 637 SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); 638 } else 639 if (!squashfs_get_cached_block(s, (char *) 640 inodep, block, offset, 641 sizeof(*inodep), &next_block, 642 &next_offset)) 643 goto failed_read; 644 645 frag_blk = SQUASHFS_INVALID_BLK; 646 if (inodep->fragment != SQUASHFS_INVALID_FRAG && 647 !get_fragment_location(s, 648 inodep->fragment, &frag_blk, &frag_size)) 649 goto failed_read; 650 651 if((i = squashfs_new_inode(s, inodeb)) == NULL) 652 goto failed_read1; 653 654 i->i_nlink = inodep->nlink; 655 i->i_size = inodep->file_size; 656 i->i_fop = &generic_ro_fops; 657 i->i_mode |= S_IFREG; 658 i->i_blocks = ((i->i_size - 1) >> 9) + 1; 659 SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; 660 SQUASHFS_I(i)->u.s1.fragment_size = frag_size; 661 SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; 662 SQUASHFS_I(i)->start_block = inodep->start_block; 663 SQUASHFS_I(i)->u.s1.block_list_start = next_block; 664 SQUASHFS_I(i)->offset = next_offset; 665 if (sblk->block_size > 4096) 666 i->i_data.a_ops = &squashfs_aops; 667 else 668 i->i_data.a_ops = &squashfs_aops_4K; 669 670 TRACE("File inode %x:%x, start_block %llx, " 671 "block_list_start %llx, offset %x\n", 672 SQUASHFS_INODE_BLK(inode), offset, 673 inodep->start_block, next_block, 674 next_offset); 675 break; 676 } 677 case SQUASHFS_DIR_TYPE: { 678 struct squashfs_dir_inode_header *inodep = &id.dir; 679 struct squashfs_dir_inode_header *sinodep = &sid.dir; 680 681 if (msblk->swap) { 682 if (!squashfs_get_cached_block(s, (char *) 683 sinodep, block, offset, 684 sizeof(*sinodep), &next_block, 685 &next_offset)) 686 goto failed_read; 687 SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); 688 } else 689 if (!squashfs_get_cached_block(s, (char *) 690 inodep, block, offset, 691 sizeof(*inodep), &next_block, 692 &next_offset)) 693 goto failed_read; 694 695 if((i = squashfs_new_inode(s, inodeb)) == NULL) 696 goto failed_read1; 697 698 i->i_nlink = inodep->nlink; 699 i->i_size = inodep->file_size; 700 i->i_op = &squashfs_dir_inode_ops; 701 i->i_fop = &squashfs_dir_ops; 702 i->i_mode |= S_IFDIR; 703 SQUASHFS_I(i)->start_block = inodep->start_block; 704 SQUASHFS_I(i)->offset = inodep->offset; 705 SQUASHFS_I(i)->u.s2.directory_index_count = 0; 706 SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; 707 708 TRACE("Directory inode %x:%x, start_block %x, offset " 709 "%x\n", SQUASHFS_INODE_BLK(inode), 710 offset, inodep->start_block, 711 inodep->offset); 712 break; 713 } 714 case SQUASHFS_LDIR_TYPE: { 715 struct squashfs_ldir_inode_header *inodep = &id.ldir; 716 struct squashfs_ldir_inode_header *sinodep = &sid.ldir; 717 718 if (msblk->swap) { 719 if (!squashfs_get_cached_block(s, (char *) 720 sinodep, block, offset, 721 sizeof(*sinodep), &next_block, 722 &next_offset)) 723 goto failed_read; 724 SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, 725 sinodep); 726 } else 727 if (!squashfs_get_cached_block(s, (char *) 728 inodep, block, offset, 729 sizeof(*inodep), &next_block, 730 &next_offset)) 731 goto failed_read; 732 733 if((i = squashfs_new_inode(s, inodeb)) == NULL) 734 goto failed_read1; 735 736 i->i_nlink = inodep->nlink; 737 i->i_size = inodep->file_size; 738 i->i_op = &squashfs_dir_inode_ops; 739 i->i_fop = &squashfs_dir_ops; 740 i->i_mode |= S_IFDIR; 741 SQUASHFS_I(i)->start_block = inodep->start_block; 742 SQUASHFS_I(i)->offset = inodep->offset; 743 SQUASHFS_I(i)->u.s2.directory_index_start = next_block; 744 SQUASHFS_I(i)->u.s2.directory_index_offset = 745 next_offset; 746 SQUASHFS_I(i)->u.s2.directory_index_count = 747 inodep->i_count; 748 SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; 749 750 TRACE("Long directory inode %x:%x, start_block %x, " 751 "offset %x\n", 752 SQUASHFS_INODE_BLK(inode), offset, 753 inodep->start_block, inodep->offset); 754 break; 755 } 756 case SQUASHFS_SYMLINK_TYPE: { 757 struct squashfs_symlink_inode_header *inodep = 758 &id.symlink; 759 struct squashfs_symlink_inode_header *sinodep = 760 &sid.symlink; 761 762 if (msblk->swap) { 763 if (!squashfs_get_cached_block(s, (char *) 764 sinodep, block, offset, 765 sizeof(*sinodep), &next_block, 766 &next_offset)) 767 goto failed_read; 768 SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, 769 sinodep); 770 } else 771 if (!squashfs_get_cached_block(s, (char *) 772 inodep, block, offset, 773 sizeof(*inodep), &next_block, 774 &next_offset)) 775 goto failed_read; 776 777 if((i = squashfs_new_inode(s, inodeb)) == NULL) 778 goto failed_read1; 779 780 i->i_nlink = inodep->nlink; 781 i->i_size = inodep->symlink_size; 782 i->i_op = &page_symlink_inode_operations; 783 i->i_data.a_ops = &squashfs_symlink_aops; 784 i->i_mode |= S_IFLNK; 785 SQUASHFS_I(i)->start_block = next_block; 786 SQUASHFS_I(i)->offset = next_offset; 787 788 TRACE("Symbolic link inode %x:%x, start_block %llx, " 789 "offset %x\n", 790 SQUASHFS_INODE_BLK(inode), offset, 791 next_block, next_offset); 792 break; 793 } 794 case SQUASHFS_BLKDEV_TYPE: 795 case SQUASHFS_CHRDEV_TYPE: { 796 struct squashfs_dev_inode_header *inodep = &id.dev; 797 struct squashfs_dev_inode_header *sinodep = &sid.dev; 798 799 if (msblk->swap) { 800 if (!squashfs_get_cached_block(s, (char *) 801 sinodep, block, offset, 802 sizeof(*sinodep), &next_block, 803 &next_offset)) 804 goto failed_read; 805 SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); 806 } else 807 if (!squashfs_get_cached_block(s, (char *) 808 inodep, block, offset, 809 sizeof(*inodep), &next_block, 810 &next_offset)) 811 goto failed_read; 812 813 if ((i = squashfs_new_inode(s, inodeb)) == NULL) 814 goto failed_read1; 815 816 i->i_nlink = inodep->nlink; 817 i->i_mode |= (inodeb->inode_type == 818 SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : 819 S_IFBLK; 820 init_special_inode(i, i->i_mode, 821 old_decode_dev(inodep->rdev)); 822 823 TRACE("Device inode %x:%x, rdev %x\n", 824 SQUASHFS_INODE_BLK(inode), offset, 825 inodep->rdev); 826 break; 827 } 828 case SQUASHFS_FIFO_TYPE: 829 case SQUASHFS_SOCKET_TYPE: { 830 struct squashfs_ipc_inode_header *inodep = &id.ipc; 831 struct squashfs_ipc_inode_header *sinodep = &sid.ipc; 832 833 if (msblk->swap) { 834 if (!squashfs_get_cached_block(s, (char *) 835 sinodep, block, offset, 836 sizeof(*sinodep), &next_block, 837 &next_offset)) 838 goto failed_read; 839 SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); 840 } else 841 if (!squashfs_get_cached_block(s, (char *) 842 inodep, block, offset, 843 sizeof(*inodep), &next_block, 844 &next_offset)) 845 goto failed_read; 846 847 if ((i = squashfs_new_inode(s, inodeb)) == NULL) 848 goto failed_read1; 849 850 i->i_nlink = inodep->nlink; 851 i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) 852 ? S_IFIFO : S_IFSOCK; 853 init_special_inode(i, i->i_mode, 0); 854 break; 855 } 856 default: 857 ERROR("Unknown inode type %d in squashfs_iget!\n", 858 inodeb->inode_type); 859 goto failed_read1; 860 } 861 862 insert_inode_hash(i); 863 return i; 864 865 failed_read: 866 ERROR("Unable to read inode [%llx:%x]\n", block, offset); 867 868 failed_read1: 869 return NULL; 870 } 871 872 873 static int read_fragment_index_table(struct super_block *s) 874 { 875 struct squashfs_sb_info *msblk = s->s_fs_info; 876 struct squashfs_super_block *sblk = &msblk->sblk; 877 878 /* Allocate fragment index table */ 879 if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES 880 (sblk->fragments), GFP_KERNEL))) { 881 ERROR("Failed to allocate uid/gid table\n"); 882 return 0; 883 } 884 885 if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && 886 !squashfs_read_data(s, (char *) 887 msblk->fragment_index, 888 sblk->fragment_table_start, 889 SQUASHFS_FRAGMENT_INDEX_BYTES 890 (sblk->fragments) | 891 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 892 ERROR("unable to read fragment index table\n"); 893 return 0; 894 } 895 896 if (msblk->swap) { 897 int i; 898 long long fragment; 899 900 for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); 901 i++) { 902 SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), 903 &msblk->fragment_index[i], 1); 904 msblk->fragment_index[i] = fragment; 905 } 906 } 907 908 return 1; 909 } 910 911 912 static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) 913 { 914 struct squashfs_super_block *sblk = &msblk->sblk; 915 916 msblk->iget = squashfs_iget; 917 msblk->read_blocklist = read_blocklist; 918 msblk->read_fragment_index_table = read_fragment_index_table; 919 920 if (sblk->s_major == 1) { 921 if (!squashfs_1_0_supported(msblk)) { 922 SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " 923 "are unsupported\n"); 924 SERROR("Please recompile with " 925 "Squashfs 1.0 support enabled\n"); 926 return 0; 927 } 928 } else if (sblk->s_major == 2) { 929 if (!squashfs_2_0_supported(msblk)) { 930 SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " 931 "are unsupported\n"); 932 SERROR("Please recompile with " 933 "Squashfs 2.0 support enabled\n"); 934 return 0; 935 } 936 } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > 937 SQUASHFS_MINOR) { 938 SERROR("Major/Minor mismatch, trying to mount newer %d.%d " 939 "filesystem\n", sblk->s_major, sblk->s_minor); 940 SERROR("Please update your kernel\n"); 941 return 0; 942 } 943 944 return 1; 945 } 946 947 948 static int squashfs_fill_super(struct super_block *s, void *data, int silent) 949 { 950 struct squashfs_sb_info *msblk; 951 struct squashfs_super_block *sblk; 952 int i; 953 char b[BDEVNAME_SIZE]; 954 struct inode *root; 955 956 TRACE("Entered squashfs_read_superblock\n"); 957 958 if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info), 959 GFP_KERNEL))) { 960 ERROR("Failed to allocate superblock\n"); 961 goto failure; 962 } 963 memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info)); 964 msblk = s->s_fs_info; 965 if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { 966 ERROR("Failed to allocate zlib workspace\n"); 967 goto failure; 968 } 969 sblk = &msblk->sblk; 970 971 msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); 972 msblk->devblksize_log2 = ffz(~msblk->devblksize); 973 974 init_MUTEX(&msblk->read_data_mutex); 975 init_MUTEX(&msblk->read_page_mutex); 976 init_MUTEX(&msblk->block_cache_mutex); 977 init_MUTEX(&msblk->fragment_mutex); 978 init_MUTEX(&msblk->meta_index_mutex); 979 980 init_waitqueue_head(&msblk->waitq); 981 init_waitqueue_head(&msblk->fragment_wait_queue); 982 983 if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, 984 sizeof(struct squashfs_super_block) | 985 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 986 SERROR("unable to read superblock\n"); 987 goto failed_mount; 988 } 989 990 /* Check it is a SQUASHFS superblock */ 991 msblk->swap = 0; 992 if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { 993 if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { 994 struct squashfs_super_block ssblk; 995 996 WARNING("Mounting a different endian SQUASHFS " 997 "filesystem on %s\n", bdevname(s->s_bdev, b)); 998 999 SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); 1000 memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); 1001 msblk->swap = 1; 1002 } else { 1003 SERROR("Can't find a SQUASHFS superblock on %s\n", 1004 bdevname(s->s_bdev, b)); 1005 goto failed_mount; 1006 } 1007 } 1008 1009 /* Check the MAJOR & MINOR versions */ 1010 if(!supported_squashfs_filesystem(msblk, silent)) 1011 goto failed_mount; 1012 1013 TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); 1014 TRACE("Inodes are %scompressed\n", 1015 SQUASHFS_UNCOMPRESSED_INODES 1016 (sblk->flags) ? "un" : ""); 1017 TRACE("Data is %scompressed\n", 1018 SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) 1019 ? "un" : ""); 1020 TRACE("Check data is %s present in the filesystem\n", 1021 SQUASHFS_CHECK_DATA(sblk->flags) ? 1022 "" : "not"); 1023 TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); 1024 TRACE("Block size %d\n", sblk->block_size); 1025 TRACE("Number of inodes %d\n", sblk->inodes); 1026 if (sblk->s_major > 1) 1027 TRACE("Number of fragments %d\n", sblk->fragments); 1028 TRACE("Number of uids %d\n", sblk->no_uids); 1029 TRACE("Number of gids %d\n", sblk->no_guids); 1030 TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); 1031 TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); 1032 if (sblk->s_major > 1) 1033 TRACE("sblk->fragment_table_start %llx\n", 1034 sblk->fragment_table_start); 1035 TRACE("sblk->uid_start %llx\n", sblk->uid_start); 1036 1037 s->s_flags |= MS_RDONLY; 1038 s->s_op = &squashfs_ops; 1039 1040 /* Init inode_table block pointer array */ 1041 if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * 1042 SQUASHFS_CACHED_BLKS, GFP_KERNEL))) { 1043 ERROR("Failed to allocate block cache\n"); 1044 goto failed_mount; 1045 } 1046 1047 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 1048 msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; 1049 1050 msblk->next_cache = 0; 1051 1052 /* Allocate read_data block */ 1053 msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ? 1054 SQUASHFS_METADATA_SIZE : 1055 sblk->block_size; 1056 1057 if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) { 1058 ERROR("Failed to allocate read_data block\n"); 1059 goto failed_mount; 1060 } 1061 1062 /* Allocate read_page block */ 1063 if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) { 1064 ERROR("Failed to allocate read_page block\n"); 1065 goto failed_mount; 1066 } 1067 1068 /* Allocate uid and gid tables */ 1069 if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * 1070 sizeof(unsigned int), GFP_KERNEL))) { 1071 ERROR("Failed to allocate uid/gid table\n"); 1072 goto failed_mount; 1073 } 1074 msblk->guid = msblk->uid + sblk->no_uids; 1075 1076 if (msblk->swap) { 1077 unsigned int suid[sblk->no_uids + sblk->no_guids]; 1078 1079 if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, 1080 ((sblk->no_uids + sblk->no_guids) * 1081 sizeof(unsigned int)) | 1082 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 1083 ERROR("unable to read uid/gid table\n"); 1084 goto failed_mount; 1085 } 1086 1087 SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + 1088 sblk->no_guids), (sizeof(unsigned int) * 8)); 1089 } else 1090 if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, 1091 ((sblk->no_uids + sblk->no_guids) * 1092 sizeof(unsigned int)) | 1093 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 1094 ERROR("unable to read uid/gid table\n"); 1095 goto failed_mount; 1096 } 1097 1098 1099 if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) 1100 goto allocate_root; 1101 1102 if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) * 1103 SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) { 1104 ERROR("Failed to allocate fragment block cache\n"); 1105 goto failed_mount; 1106 } 1107 1108 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { 1109 msblk->fragment[i].locked = 0; 1110 msblk->fragment[i].block = SQUASHFS_INVALID_BLK; 1111 msblk->fragment[i].data = NULL; 1112 } 1113 1114 msblk->next_fragment = 0; 1115 1116 /* Allocate fragment index table */ 1117 if (msblk->read_fragment_index_table(s) == 0) 1118 goto failed_mount; 1119 1120 allocate_root: 1121 if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL) 1122 goto failed_mount; 1123 1124 if ((s->s_root = d_alloc_root(root)) == NULL) { 1125 ERROR("Root inode create failed\n"); 1126 iput(root); 1127 goto failed_mount; 1128 } 1129 1130 TRACE("Leaving squashfs_read_super\n"); 1131 return 0; 1132 1133 failed_mount: 1134 kfree(msblk->fragment_index); 1135 kfree(msblk->fragment); 1136 kfree(msblk->uid); 1137 kfree(msblk->read_page); 1138 kfree(msblk->read_data); 1139 kfree(msblk->block_cache); 1140 kfree(msblk->fragment_index_2); 1141 vfree(msblk->stream.workspace); 1142 kfree(s->s_fs_info); 1143 s->s_fs_info = NULL; 1144 return -EINVAL; 1145 1146 failure: 1147 return -ENOMEM; 1148 } 1149 1150 1151 static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) 1152 { 1153 struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; 1154 struct squashfs_super_block *sblk = &msblk->sblk; 1155 1156 TRACE("Entered squashfs_statfs\n"); 1157 1158 buf->f_type = SQUASHFS_MAGIC; 1159 buf->f_bsize = sblk->block_size; 1160 buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; 1161 buf->f_bfree = buf->f_bavail = 0; 1162 buf->f_files = sblk->inodes; 1163 buf->f_ffree = 0; 1164 buf->f_namelen = SQUASHFS_NAME_LEN; 1165 1166 return 0; 1167 } 1168 1169 1170 static int squashfs_symlink_readpage(struct file *file, struct page *page) 1171 { 1172 struct inode *inode = page->mapping->host; 1173 int index = page->index << PAGE_CACHE_SHIFT, length, bytes; 1174 long long block = SQUASHFS_I(inode)->start_block; 1175 int offset = SQUASHFS_I(inode)->offset; 1176 void *pageaddr = kmap(page); 1177 1178 TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " 1179 "%llx, offset %x\n", page->index, 1180 SQUASHFS_I(inode)->start_block, 1181 SQUASHFS_I(inode)->offset); 1182 1183 for (length = 0; length < index; length += bytes) { 1184 if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, 1185 block, offset, PAGE_CACHE_SIZE, &block, 1186 &offset))) { 1187 ERROR("Unable to read symbolic link [%llx:%x]\n", block, 1188 offset); 1189 goto skip_read; 1190 } 1191 } 1192 1193 if (length != index) { 1194 ERROR("(squashfs_symlink_readpage) length != index\n"); 1195 bytes = 0; 1196 goto skip_read; 1197 } 1198 1199 bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : 1200 i_size_read(inode) - length; 1201 1202 if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, 1203 offset, bytes, &block, &offset))) 1204 ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); 1205 1206 skip_read: 1207 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 1208 kunmap(page); 1209 SetPageUptodate(page); 1210 unlock_page(page); 1211 1212 return 0; 1213 } 1214 1215 1216 struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) 1217 { 1218 struct meta_index *meta = NULL; 1219 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; 1220 int i; 1221 1222 down(&msblk->meta_index_mutex); 1223 1224 TRACE("locate_meta_index: index %d, offset %d\n", index, offset); 1225 1226 if(msblk->meta_index == NULL) 1227 goto not_allocated; 1228 1229 for (i = 0; i < SQUASHFS_META_NUMBER; i ++) 1230 if (msblk->meta_index[i].inode_number == inode->i_ino && 1231 msblk->meta_index[i].offset >= offset && 1232 msblk->meta_index[i].offset <= index && 1233 msblk->meta_index[i].locked == 0) { 1234 TRACE("locate_meta_index: entry %d, offset %d\n", i, 1235 msblk->meta_index[i].offset); 1236 meta = &msblk->meta_index[i]; 1237 offset = meta->offset; 1238 } 1239 1240 if (meta) 1241 meta->locked = 1; 1242 1243 not_allocated: 1244 up(&msblk->meta_index_mutex); 1245 1246 return meta; 1247 } 1248 1249 1250 struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) 1251 { 1252 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; 1253 struct meta_index *meta = NULL; 1254 int i; 1255 1256 down(&msblk->meta_index_mutex); 1257 1258 TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); 1259 1260 if(msblk->meta_index == NULL) { 1261 if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) * 1262 SQUASHFS_META_NUMBER, GFP_KERNEL))) { 1263 ERROR("Failed to allocate meta_index\n"); 1264 goto failed; 1265 } 1266 for(i = 0; i < SQUASHFS_META_NUMBER; i++) { 1267 msblk->meta_index[i].inode_number = 0; 1268 msblk->meta_index[i].locked = 0; 1269 } 1270 msblk->next_meta_index = 0; 1271 } 1272 1273 for(i = SQUASHFS_META_NUMBER; i && 1274 msblk->meta_index[msblk->next_meta_index].locked; i --) 1275 msblk->next_meta_index = (msblk->next_meta_index + 1) % 1276 SQUASHFS_META_NUMBER; 1277 1278 if(i == 0) { 1279 TRACE("empty_meta_index: failed!\n"); 1280 goto failed; 1281 } 1282 1283 TRACE("empty_meta_index: returned meta entry %d, %p\n", 1284 msblk->next_meta_index, 1285 &msblk->meta_index[msblk->next_meta_index]); 1286 1287 meta = &msblk->meta_index[msblk->next_meta_index]; 1288 msblk->next_meta_index = (msblk->next_meta_index + 1) % 1289 SQUASHFS_META_NUMBER; 1290 1291 meta->inode_number = inode->i_ino; 1292 meta->offset = offset; 1293 meta->skip = skip; 1294 meta->entries = 0; 1295 meta->locked = 1; 1296 1297 failed: 1298 up(&msblk->meta_index_mutex); 1299 return meta; 1300 } 1301 1302 1303 void release_meta_index(struct inode *inode, struct meta_index *meta) 1304 { 1305 meta->locked = 0; 1306 } 1307 1308 1309 static int read_block_index(struct super_block *s, int blocks, char *block_list, 1310 long long *start_block, int *offset) 1311 { 1312 struct squashfs_sb_info *msblk = s->s_fs_info; 1313 unsigned int *block_listp; 1314 int block = 0; 1315 1316 if (msblk->swap) { 1317 char sblock_list[blocks << 2]; 1318 1319 if (!squashfs_get_cached_block(s, sblock_list, *start_block, 1320 *offset, blocks << 2, start_block, offset)) { 1321 ERROR("Unable to read block list [%llx:%x]\n", 1322 *start_block, *offset); 1323 goto failure; 1324 } 1325 SQUASHFS_SWAP_INTS(((unsigned int *)block_list), 1326 ((unsigned int *)sblock_list), blocks); 1327 } else 1328 if (!squashfs_get_cached_block(s, block_list, *start_block, 1329 *offset, blocks << 2, start_block, offset)) { 1330 ERROR("Unable to read block list [%llx:%x]\n", 1331 *start_block, *offset); 1332 goto failure; 1333 } 1334 1335 for (block_listp = (unsigned int *) block_list; blocks; 1336 block_listp++, blocks --) 1337 block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); 1338 1339 return block; 1340 1341 failure: 1342 return -1; 1343 } 1344 1345 1346 #define SIZE 256 1347 1348 static inline int calculate_skip(int blocks) { 1349 int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); 1350 return skip >= 7 ? 7 : skip + 1; 1351 } 1352 1353 1354 static int get_meta_index(struct inode *inode, int index, 1355 long long *index_block, int *index_offset, 1356 long long *data_block, char *block_list) 1357 { 1358 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; 1359 struct squashfs_super_block *sblk = &msblk->sblk; 1360 int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); 1361 int offset = 0; 1362 struct meta_index *meta; 1363 struct meta_entry *meta_entry; 1364 long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; 1365 int cur_offset = SQUASHFS_I(inode)->offset; 1366 long long cur_data_block = SQUASHFS_I(inode)->start_block; 1367 int i; 1368 1369 index /= SQUASHFS_META_INDEXES * skip; 1370 1371 while ( offset < index ) { 1372 meta = locate_meta_index(inode, index, offset + 1); 1373 1374 if (meta == NULL) { 1375 if ((meta = empty_meta_index(inode, offset + 1, 1376 skip)) == NULL) 1377 goto all_done; 1378 } else { 1379 offset = index < meta->offset + meta->entries ? index : 1380 meta->offset + meta->entries - 1; 1381 meta_entry = &meta->meta_entry[offset - meta->offset]; 1382 cur_index_block = meta_entry->index_block + sblk->inode_table_start; 1383 cur_offset = meta_entry->offset; 1384 cur_data_block = meta_entry->data_block; 1385 TRACE("get_meta_index: offset %d, meta->offset %d, " 1386 "meta->entries %d\n", offset, meta->offset, 1387 meta->entries); 1388 TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" 1389 " data_block 0x%llx\n", cur_index_block, 1390 cur_offset, cur_data_block); 1391 } 1392 1393 for (i = meta->offset + meta->entries; i <= index && 1394 i < meta->offset + SQUASHFS_META_ENTRIES; i++) { 1395 int blocks = skip * SQUASHFS_META_INDEXES; 1396 1397 while (blocks) { 1398 int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : 1399 blocks; 1400 int res = read_block_index(inode->i_sb, block, 1401 block_list, &cur_index_block, 1402 &cur_offset); 1403 1404 if (res == -1) 1405 goto failed; 1406 1407 cur_data_block += res; 1408 blocks -= block; 1409 } 1410 1411 meta_entry = &meta->meta_entry[i - meta->offset]; 1412 meta_entry->index_block = cur_index_block - sblk->inode_table_start; 1413 meta_entry->offset = cur_offset; 1414 meta_entry->data_block = cur_data_block; 1415 meta->entries ++; 1416 offset ++; 1417 } 1418 1419 TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", 1420 meta->offset, meta->entries); 1421 1422 release_meta_index(inode, meta); 1423 } 1424 1425 all_done: 1426 *index_block = cur_index_block; 1427 *index_offset = cur_offset; 1428 *data_block = cur_data_block; 1429 1430 return offset * SQUASHFS_META_INDEXES * skip; 1431 1432 failed: 1433 release_meta_index(inode, meta); 1434 return -1; 1435 } 1436 1437 1438 static long long read_blocklist(struct inode *inode, int index, 1439 int readahead_blks, char *block_list, 1440 unsigned short **block_p, unsigned int *bsize) 1441 { 1442 long long block_ptr; 1443 int offset; 1444 long long block; 1445 int res = get_meta_index(inode, index, &block_ptr, &offset, &block, 1446 block_list); 1447 1448 TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" 1449 " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, 1450 block); 1451 1452 if(res == -1) 1453 goto failure; 1454 1455 index -= res; 1456 1457 while ( index ) { 1458 int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; 1459 int res = read_block_index(inode->i_sb, blocks, block_list, 1460 &block_ptr, &offset); 1461 if (res == -1) 1462 goto failure; 1463 block += res; 1464 index -= blocks; 1465 } 1466 1467 if (read_block_index(inode->i_sb, 1, block_list, 1468 &block_ptr, &offset) == -1) 1469 goto failure; 1470 *bsize = *((unsigned int *) block_list); 1471 1472 return block; 1473 1474 failure: 1475 return 0; 1476 } 1477 1478 1479 static int squashfs_readpage(struct file *file, struct page *page) 1480 { 1481 struct inode *inode = page->mapping->host; 1482 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; 1483 struct squashfs_super_block *sblk = &msblk->sblk; 1484 unsigned char *block_list; 1485 long long block; 1486 unsigned int bsize, i = 0, bytes = 0, byte_offset = 0; 1487 int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); 1488 void *pageaddr; 1489 struct squashfs_fragment_cache *fragment = NULL; 1490 char *data_ptr = msblk->read_page; 1491 1492 int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; 1493 int start_index = page->index & ~mask; 1494 int end_index = start_index | mask; 1495 1496 TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", 1497 page->index, 1498 SQUASHFS_I(inode)->start_block); 1499 1500 if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { 1501 ERROR("Failed to allocate block_list\n"); 1502 goto skip_read; 1503 } 1504 1505 if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> 1506 PAGE_CACHE_SHIFT)) 1507 goto skip_read; 1508 1509 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 1510 || index < (i_size_read(inode) >> 1511 sblk->block_log)) { 1512 if ((block = (msblk->read_blocklist)(inode, index, 1, 1513 block_list, NULL, &bsize)) == 0) 1514 goto skip_read; 1515 1516 down(&msblk->read_page_mutex); 1517 1518 if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, 1519 block, bsize, NULL))) { 1520 ERROR("Unable to read page, block %llx, size %x\n", block, 1521 bsize); 1522 up(&msblk->read_page_mutex); 1523 goto skip_read; 1524 } 1525 } else { 1526 if ((fragment = get_cached_fragment(inode->i_sb, 1527 SQUASHFS_I(inode)-> 1528 u.s1.fragment_start_block, 1529 SQUASHFS_I(inode)->u.s1.fragment_size)) 1530 == NULL) { 1531 ERROR("Unable to read page, block %llx, size %x\n", 1532 SQUASHFS_I(inode)-> 1533 u.s1.fragment_start_block, 1534 (int) SQUASHFS_I(inode)-> 1535 u.s1.fragment_size); 1536 goto skip_read; 1537 } 1538 bytes = SQUASHFS_I(inode)->u.s1.fragment_offset + 1539 (i_size_read(inode) & (sblk->block_size 1540 - 1)); 1541 byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset; 1542 data_ptr = fragment->data; 1543 } 1544 1545 for (i = start_index; i <= end_index && byte_offset < bytes; 1546 i++, byte_offset += PAGE_CACHE_SIZE) { 1547 struct page *push_page; 1548 int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? 1549 PAGE_CACHE_SIZE : bytes - byte_offset; 1550 1551 TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", 1552 bytes, i, byte_offset, available_bytes); 1553 1554 if (i == page->index) { 1555 pageaddr = kmap_atomic(page, KM_USER0); 1556 memcpy(pageaddr, data_ptr + byte_offset, 1557 available_bytes); 1558 memset(pageaddr + available_bytes, 0, 1559 PAGE_CACHE_SIZE - available_bytes); 1560 kunmap_atomic(pageaddr, KM_USER0); 1561 flush_dcache_page(page); 1562 SetPageUptodate(page); 1563 unlock_page(page); 1564 } else if ((push_page = 1565 grab_cache_page_nowait(page->mapping, i))) { 1566 pageaddr = kmap_atomic(push_page, KM_USER0); 1567 1568 memcpy(pageaddr, data_ptr + byte_offset, 1569 available_bytes); 1570 memset(pageaddr + available_bytes, 0, 1571 PAGE_CACHE_SIZE - available_bytes); 1572 kunmap_atomic(pageaddr, KM_USER0); 1573 flush_dcache_page(push_page); 1574 SetPageUptodate(push_page); 1575 unlock_page(push_page); 1576 page_cache_release(push_page); 1577 } 1578 } 1579 1580 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 1581 || index < (i_size_read(inode) >> 1582 sblk->block_log)) 1583 up(&msblk->read_page_mutex); 1584 else 1585 release_cached_fragment(msblk, fragment); 1586 1587 kfree(block_list); 1588 return 0; 1589 1590 skip_read: 1591 pageaddr = kmap_atomic(page, KM_USER0); 1592 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 1593 kunmap_atomic(pageaddr, KM_USER0); 1594 flush_dcache_page(page); 1595 SetPageUptodate(page); 1596 unlock_page(page); 1597 1598 kfree(block_list); 1599 return 0; 1600 } 1601 1602 1603 static int squashfs_readpage4K(struct file *file, struct page *page) 1604 { 1605 struct inode *inode = page->mapping->host; 1606 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; 1607 struct squashfs_super_block *sblk = &msblk->sblk; 1608 unsigned char *block_list; 1609 long long block; 1610 unsigned int bsize, bytes = 0; 1611 void *pageaddr; 1612 1613 TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n", 1614 page->index, 1615 SQUASHFS_I(inode)->start_block); 1616 1617 if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> 1618 PAGE_CACHE_SHIFT)) { 1619 pageaddr = kmap_atomic(page, KM_USER0); 1620 block_list = NULL; 1621 goto skip_read; 1622 } 1623 1624 if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { 1625 ERROR("Failed to allocate block_list\n"); 1626 pageaddr = kmap_atomic(page, KM_USER0); 1627 block_list = NULL; 1628 goto skip_read; 1629 } 1630 1631 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 1632 || page->index < (i_size_read(inode) >> 1633 sblk->block_log)) { 1634 block = (msblk->read_blocklist)(inode, page->index, 1, 1635 block_list, NULL, &bsize); 1636 1637 down(&msblk->read_page_mutex); 1638 bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, 1639 bsize, NULL); 1640 pageaddr = kmap_atomic(page, KM_USER0); 1641 if (bytes) 1642 memcpy(pageaddr, msblk->read_page, bytes); 1643 else 1644 ERROR("Unable to read page, block %llx, size %x\n", 1645 block, bsize); 1646 up(&msblk->read_page_mutex); 1647 } else { 1648 struct squashfs_fragment_cache *fragment = 1649 get_cached_fragment(inode->i_sb, 1650 SQUASHFS_I(inode)-> 1651 u.s1.fragment_start_block, 1652 SQUASHFS_I(inode)-> u.s1.fragment_size); 1653 pageaddr = kmap_atomic(page, KM_USER0); 1654 if (fragment) { 1655 bytes = i_size_read(inode) & (sblk->block_size - 1); 1656 memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> 1657 u.s1.fragment_offset, bytes); 1658 release_cached_fragment(msblk, fragment); 1659 } else 1660 ERROR("Unable to read page, block %llx, size %x\n", 1661 SQUASHFS_I(inode)-> 1662 u.s1.fragment_start_block, (int) 1663 SQUASHFS_I(inode)-> u.s1.fragment_size); 1664 } 1665 1666 skip_read: 1667 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 1668 kunmap_atomic(pageaddr, KM_USER0); 1669 flush_dcache_page(page); 1670 SetPageUptodate(page); 1671 unlock_page(page); 1672 1673 kfree(block_list); 1674 return 0; 1675 } 1676 1677 1678 static int get_dir_index_using_offset(struct super_block *s, long long 1679 *next_block, unsigned int *next_offset, 1680 long long index_start, 1681 unsigned int index_offset, int i_count, 1682 long long f_pos) 1683 { 1684 struct squashfs_sb_info *msblk = s->s_fs_info; 1685 struct squashfs_super_block *sblk = &msblk->sblk; 1686 int i, length = 0; 1687 struct squashfs_dir_index index; 1688 1689 TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", 1690 i_count, (unsigned int) f_pos); 1691 1692 f_pos =- 3; 1693 if (f_pos == 0) 1694 goto finish; 1695 1696 for (i = 0; i < i_count; i++) { 1697 if (msblk->swap) { 1698 struct squashfs_dir_index sindex; 1699 squashfs_get_cached_block(s, (char *) &sindex, 1700 index_start, index_offset, 1701 sizeof(sindex), &index_start, 1702 &index_offset); 1703 SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); 1704 } else 1705 squashfs_get_cached_block(s, (char *) &index, 1706 index_start, index_offset, 1707 sizeof(index), &index_start, 1708 &index_offset); 1709 1710 if (index.index > f_pos) 1711 break; 1712 1713 squashfs_get_cached_block(s, NULL, index_start, index_offset, 1714 index.size + 1, &index_start, 1715 &index_offset); 1716 1717 length = index.index; 1718 *next_block = index.start_block + sblk->directory_table_start; 1719 } 1720 1721 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 1722 1723 finish: 1724 return length + 3; 1725 } 1726 1727 1728 static int get_dir_index_using_name(struct super_block *s, long long 1729 *next_block, unsigned int *next_offset, 1730 long long index_start, 1731 unsigned int index_offset, int i_count, 1732 const char *name, int size) 1733 { 1734 struct squashfs_sb_info *msblk = s->s_fs_info; 1735 struct squashfs_super_block *sblk = &msblk->sblk; 1736 int i, length = 0; 1737 struct squashfs_dir_index *index; 1738 char *str; 1739 1740 TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); 1741 1742 if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + 1743 (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { 1744 ERROR("Failed to allocate squashfs_dir_index\n"); 1745 goto failure; 1746 } 1747 1748 index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); 1749 strncpy(str, name, size); 1750 str[size] = '\0'; 1751 1752 for (i = 0; i < i_count; i++) { 1753 if (msblk->swap) { 1754 struct squashfs_dir_index sindex; 1755 squashfs_get_cached_block(s, (char *) &sindex, 1756 index_start, index_offset, 1757 sizeof(sindex), &index_start, 1758 &index_offset); 1759 SQUASHFS_SWAP_DIR_INDEX(index, &sindex); 1760 } else 1761 squashfs_get_cached_block(s, (char *) index, 1762 index_start, index_offset, 1763 sizeof(struct squashfs_dir_index), 1764 &index_start, &index_offset); 1765 1766 squashfs_get_cached_block(s, index->name, index_start, 1767 index_offset, index->size + 1, 1768 &index_start, &index_offset); 1769 1770 index->name[index->size + 1] = '\0'; 1771 1772 if (strcmp(index->name, str) > 0) 1773 break; 1774 1775 length = index->index; 1776 *next_block = index->start_block + sblk->directory_table_start; 1777 } 1778 1779 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 1780 kfree(str); 1781 failure: 1782 return length + 3; 1783 } 1784 1785 1786 static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) 1787 { 1788 struct inode *i = file->f_dentry->d_inode; 1789 struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; 1790 struct squashfs_super_block *sblk = &msblk->sblk; 1791 long long next_block = SQUASHFS_I(i)->start_block + 1792 sblk->directory_table_start; 1793 int next_offset = SQUASHFS_I(i)->offset, length = 0, 1794 dir_count; 1795 struct squashfs_dir_header dirh; 1796 struct squashfs_dir_entry *dire; 1797 1798 TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); 1799 1800 if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + 1801 SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { 1802 ERROR("Failed to allocate squashfs_dir_entry\n"); 1803 goto finish; 1804 } 1805 1806 while(file->f_pos < 3) { 1807 char *name; 1808 int size, i_ino; 1809 1810 if(file->f_pos == 0) { 1811 name = "."; 1812 size = 1; 1813 i_ino = i->i_ino; 1814 } else { 1815 name = ".."; 1816 size = 2; 1817 i_ino = SQUASHFS_I(i)->u.s2.parent_inode; 1818 } 1819 TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", 1820 (unsigned int) dirent, name, size, (int) 1821 file->f_pos, i_ino, 1822 squashfs_filetype_table[1]); 1823 1824 if (filldir(dirent, name, size, 1825 file->f_pos, i_ino, 1826 squashfs_filetype_table[1]) < 0) { 1827 TRACE("Filldir returned less than 0\n"); 1828 goto finish; 1829 } 1830 file->f_pos += size; 1831 } 1832 1833 length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, 1834 SQUASHFS_I(i)->u.s2.directory_index_start, 1835 SQUASHFS_I(i)->u.s2.directory_index_offset, 1836 SQUASHFS_I(i)->u.s2.directory_index_count, 1837 file->f_pos); 1838 1839 while (length < i_size_read(i)) { 1840 /* read directory header */ 1841 if (msblk->swap) { 1842 struct squashfs_dir_header sdirh; 1843 1844 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 1845 next_block, next_offset, sizeof(sdirh), 1846 &next_block, &next_offset)) 1847 goto failed_read; 1848 1849 length += sizeof(sdirh); 1850 SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 1851 } else { 1852 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 1853 next_block, next_offset, sizeof(dirh), 1854 &next_block, &next_offset)) 1855 goto failed_read; 1856 1857 length += sizeof(dirh); 1858 } 1859 1860 dir_count = dirh.count + 1; 1861 while (dir_count--) { 1862 if (msblk->swap) { 1863 struct squashfs_dir_entry sdire; 1864 if (!squashfs_get_cached_block(i->i_sb, (char *) 1865 &sdire, next_block, next_offset, 1866 sizeof(sdire), &next_block, 1867 &next_offset)) 1868 goto failed_read; 1869 1870 length += sizeof(sdire); 1871 SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 1872 } else { 1873 if (!squashfs_get_cached_block(i->i_sb, (char *) 1874 dire, next_block, next_offset, 1875 sizeof(*dire), &next_block, 1876 &next_offset)) 1877 goto failed_read; 1878 1879 length += sizeof(*dire); 1880 } 1881 1882 if (!squashfs_get_cached_block(i->i_sb, dire->name, 1883 next_block, next_offset, 1884 dire->size + 1, &next_block, 1885 &next_offset)) 1886 goto failed_read; 1887 1888 length += dire->size + 1; 1889 1890 if (file->f_pos >= length) 1891 continue; 1892 1893 dire->name[dire->size + 1] = '\0'; 1894 1895 TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", 1896 (unsigned int) dirent, dire->name, 1897 dire->size + 1, (int) file->f_pos, 1898 dirh.start_block, dire->offset, 1899 dirh.inode_number + dire->inode_number, 1900 squashfs_filetype_table[dire->type]); 1901 1902 if (filldir(dirent, dire->name, dire->size + 1, 1903 file->f_pos, 1904 dirh.inode_number + dire->inode_number, 1905 squashfs_filetype_table[dire->type]) 1906 < 0) { 1907 TRACE("Filldir returned less than 0\n"); 1908 goto finish; 1909 } 1910 file->f_pos = length; 1911 } 1912 } 1913 1914 finish: 1915 kfree(dire); 1916 return 0; 1917 1918 failed_read: 1919 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 1920 next_offset); 1921 return 0; 1922 } 1923 1924 1925 static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, 1926 struct nameidata *nd) 1927 { 1928 const unsigned char *name = dentry->d_name.name; 1929 int len = dentry->d_name.len; 1930 struct inode *inode = NULL; 1931 struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; 1932 struct squashfs_super_block *sblk = &msblk->sblk; 1933 long long next_block = SQUASHFS_I(i)->start_block + 1934 sblk->directory_table_start; 1935 int next_offset = SQUASHFS_I(i)->offset, length = 0, 1936 dir_count; 1937 struct squashfs_dir_header dirh; 1938 struct squashfs_dir_entry *dire; 1939 1940 TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); 1941 1942 if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + 1943 SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { 1944 ERROR("Failed to allocate squashfs_dir_entry\n"); 1945 goto exit_loop; 1946 } 1947 1948 if (len > SQUASHFS_NAME_LEN) 1949 goto exit_loop; 1950 1951 length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, 1952 SQUASHFS_I(i)->u.s2.directory_index_start, 1953 SQUASHFS_I(i)->u.s2.directory_index_offset, 1954 SQUASHFS_I(i)->u.s2.directory_index_count, name, 1955 len); 1956 1957 while (length < i_size_read(i)) { 1958 /* read directory header */ 1959 if (msblk->swap) { 1960 struct squashfs_dir_header sdirh; 1961 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 1962 next_block, next_offset, sizeof(sdirh), 1963 &next_block, &next_offset)) 1964 goto failed_read; 1965 1966 length += sizeof(sdirh); 1967 SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 1968 } else { 1969 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 1970 next_block, next_offset, sizeof(dirh), 1971 &next_block, &next_offset)) 1972 goto failed_read; 1973 1974 length += sizeof(dirh); 1975 } 1976 1977 dir_count = dirh.count + 1; 1978 while (dir_count--) { 1979 if (msblk->swap) { 1980 struct squashfs_dir_entry sdire; 1981 if (!squashfs_get_cached_block(i->i_sb, (char *) 1982 &sdire, next_block,next_offset, 1983 sizeof(sdire), &next_block, 1984 &next_offset)) 1985 goto failed_read; 1986 1987 length += sizeof(sdire); 1988 SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 1989 } else { 1990 if (!squashfs_get_cached_block(i->i_sb, (char *) 1991 dire, next_block,next_offset, 1992 sizeof(*dire), &next_block, 1993 &next_offset)) 1994 goto failed_read; 1995 1996 length += sizeof(*dire); 1997 } 1998 1999 if (!squashfs_get_cached_block(i->i_sb, dire->name, 2000 next_block, next_offset, dire->size + 1, 2001 &next_block, &next_offset)) 2002 goto failed_read; 2003 2004 length += dire->size + 1; 2005 2006 if (name[0] < dire->name[0]) 2007 goto exit_loop; 2008 2009 if ((len == dire->size + 1) && !strncmp(name, 2010 dire->name, len)) { 2011 squashfs_inode_t ino = 2012 SQUASHFS_MKINODE(dirh.start_block, 2013 dire->offset); 2014 2015 TRACE("calling squashfs_iget for directory " 2016 "entry %s, inode %x:%x, %d\n", name, 2017 dirh.start_block, dire->offset, 2018 dirh.inode_number + dire->inode_number); 2019 2020 inode = (msblk->iget)(i->i_sb, ino); 2021 2022 goto exit_loop; 2023 } 2024 } 2025 } 2026 2027 exit_loop: 2028 kfree(dire); 2029 d_add(dentry, inode); 2030 return ERR_PTR(0); 2031 2032 failed_read: 2033 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 2034 next_offset); 2035 goto exit_loop; 2036 } 2037 2038 2039 static void squashfs_put_super(struct super_block *s) 2040 { 2041 int i; 2042 2043 if (s->s_fs_info) { 2044 struct squashfs_sb_info *sbi = s->s_fs_info; 2045 if (sbi->block_cache) 2046 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 2047 if (sbi->block_cache[i].block != 2048 SQUASHFS_INVALID_BLK) 2049 kfree(sbi->block_cache[i].data); 2050 if (sbi->fragment) 2051 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 2052 SQUASHFS_FREE(sbi->fragment[i].data); 2053 kfree(sbi->fragment); 2054 kfree(sbi->block_cache); 2055 kfree(sbi->read_data); 2056 kfree(sbi->read_page); 2057 kfree(sbi->uid); 2058 kfree(sbi->fragment_index); 2059 kfree(sbi->fragment_index_2); 2060 kfree(sbi->meta_index); 2061 vfree(sbi->stream.workspace); 2062 kfree(s->s_fs_info); 2063 s->s_fs_info = NULL; 2064 } 2065 } 2066 2067 2068 static int squashfs_get_sb(struct file_system_type *fs_type, int flags, 2069 const char *dev_name, void *data, 2070 struct vfsmount *mnt) 2071 { 2072 return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, 2073 mnt); 2074 } 2075 2076 2077 static int __init init_squashfs_fs(void) 2078 { 2079 int err = init_inodecache(); 2080 if (err) 2081 goto out; 2082 2083 printk(KERN_INFO "squashfs: version 3.1 (2006/08/19) " 2084 "Phillip Lougher\n"); 2085 2086 if ((err = register_filesystem(&squashfs_fs_type))) 2087 destroy_inodecache(); 2088 2089 out: 2090 return err; 2091 } 2092 2093 2094 static void __exit exit_squashfs_fs(void) 2095 { 2096 unregister_filesystem(&squashfs_fs_type); 2097 destroy_inodecache(); 2098 } 2099 2100 2101 static kmem_cache_t * squashfs_inode_cachep; 2102 2103 2104 static struct inode *squashfs_alloc_inode(struct super_block *sb) 2105 { 2106 struct squashfs_inode_info *ei; 2107 ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); 2108 if (!ei) 2109 return NULL; 2110 return &ei->vfs_inode; 2111 } 2112 2113 2114 static void squashfs_destroy_inode(struct inode *inode) 2115 { 2116 kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); 2117 } 2118 2119 2120 static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) 2121 { 2122 struct squashfs_inode_info *ei = foo; 2123 2124 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 2125 SLAB_CTOR_CONSTRUCTOR) 2126 inode_init_once(&ei->vfs_inode); 2127 } 2128 2129 2130 static int __init init_inodecache(void) 2131 { 2132 squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", 2133 sizeof(struct squashfs_inode_info), 2134 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 2135 init_once, NULL); 2136 if (squashfs_inode_cachep == NULL) 2137 return -ENOMEM; 2138 return 0; 2139 } 2140 2141 2142 static void destroy_inodecache(void) 2143 { 2144 kmem_cache_destroy(squashfs_inode_cachep); 2145 } 2146 2147 2148 module_init(init_squashfs_fs); 2149 module_exit(exit_squashfs_fs); 2150 MODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem"); 2151 MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>"); 2152 MODULE_LICENSE("GPL"); -
fs/squashfs/squashfs.h
diff -Nru linux-2.6.19.ori2/fs/squashfs/squashfs.h linux-2.6.19.ori/fs/squashfs/squashfs.h
old new 1 /* 2 * Squashfs - a compressed read only filesystem for Linux 3 * 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006 5 * Phillip Lougher <phillip@lougher.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2, 10 * or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * 21 * squashfs.h 22 */ 23 24 #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY 25 #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY 26 #endif 27 28 #ifdef SQUASHFS_TRACE 29 #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) 30 #else 31 #define TRACE(s, args...) {} 32 #endif 33 34 #define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) 35 36 #define SERROR(s, args...) do { \ 37 if (!silent) \ 38 printk(KERN_ERR "SQUASHFS error: "s, ## args);\ 39 } while(0) 40 41 #define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) 42 43 static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) 44 { 45 return list_entry(inode, struct squashfs_inode_info, vfs_inode); 46 } 47 48 #if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) 49 #define SQSH_EXTERN 50 extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, 51 long long index, unsigned int length, 52 long long *next_index); 53 extern int squashfs_get_cached_block(struct super_block *s, char *buffer, 54 long long block, unsigned int offset, 55 int length, long long *next_block, 56 unsigned int *next_offset); 57 extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct 58 squashfs_fragment_cache *fragment); 59 extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block 60 *s, long long start_block, 61 int length); 62 extern struct address_space_operations squashfs_symlink_aops; 63 extern struct address_space_operations squashfs_aops; 64 extern struct address_space_operations squashfs_aops_4K; 65 extern struct inode_operations squashfs_dir_inode_ops; 66 #else 67 #define SQSH_EXTERN static 68 #endif 69 70 #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY 71 extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); 72 #else 73 static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) 74 { 75 return 0; 76 } 77 #endif 78 79 #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY 80 extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); 81 #else 82 static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) 83 { 84 return 0; 85 } 86 #endif -
fs/squashfs/squashfs2_0.c
diff -Nru linux-2.6.19.ori2/fs/squashfs/squashfs2_0.c linux-2.6.19.ori/fs/squashfs/squashfs2_0.c
old new 1 /* 2 * Squashfs - a compressed read only filesystem for Linux 3 * 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006 5 * Phillip Lougher <phillip@lougher.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2, 10 * or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * 21 * squashfs2_0.c 22 */ 23 24 #include <linux/types.h> 25 #include <linux/squashfs_fs.h> 26 #include <linux/module.h> 27 #include <linux/errno.h> 28 #include <linux/slab.h> 29 #include <linux/zlib.h> 30 #include <linux/fs.h> 31 #include <linux/smp_lock.h> 32 #include <linux/slab.h> 33 #include <linux/squashfs_fs_sb.h> 34 #include <linux/squashfs_fs_i.h> 35 #include <linux/buffer_head.h> 36 #include <linux/vfs.h> 37 #include <linux/init.h> 38 #include <linux/dcache.h> 39 #include <linux/wait.h> 40 #include <linux/zlib.h> 41 #include <linux/blkdev.h> 42 #include <linux/vmalloc.h> 43 #include <asm/uaccess.h> 44 #include <asm/semaphore.h> 45 46 #include "squashfs.h" 47 static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); 48 static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, 49 struct nameidata *); 50 51 static struct file_operations squashfs_dir_ops_2 = { 52 .read = generic_read_dir, 53 .readdir = squashfs_readdir_2 54 }; 55 56 static struct inode_operations squashfs_dir_inode_ops_2 = { 57 .lookup = squashfs_lookup_2 58 }; 59 60 static unsigned char squashfs_filetype_table[] = { 61 DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK 62 }; 63 64 static int read_fragment_index_table_2(struct super_block *s) 65 { 66 struct squashfs_sb_info *msblk = s->s_fs_info; 67 struct squashfs_super_block *sblk = &msblk->sblk; 68 69 if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 70 (sblk->fragments), GFP_KERNEL))) { 71 ERROR("Failed to allocate uid/gid table\n"); 72 return 0; 73 } 74 75 if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && 76 !squashfs_read_data(s, (char *) 77 msblk->fragment_index_2, 78 sblk->fragment_table_start, 79 SQUASHFS_FRAGMENT_INDEX_BYTES_2 80 (sblk->fragments) | 81 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 82 ERROR("unable to read fragment index table\n"); 83 return 0; 84 } 85 86 if (msblk->swap) { 87 int i; 88 unsigned int fragment; 89 90 for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); 91 i++) { 92 SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), 93 &msblk->fragment_index_2[i], 1); 94 msblk->fragment_index_2[i] = fragment; 95 } 96 } 97 98 return 1; 99 } 100 101 102 static int get_fragment_location_2(struct super_block *s, unsigned int fragment, 103 long long *fragment_start_block, 104 unsigned int *fragment_size) 105 { 106 struct squashfs_sb_info *msblk = s->s_fs_info; 107 long long start_block = 108 msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; 109 int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); 110 struct squashfs_fragment_entry_2 fragment_entry; 111 112 if (msblk->swap) { 113 struct squashfs_fragment_entry_2 sfragment_entry; 114 115 if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, 116 start_block, offset, 117 sizeof(sfragment_entry), &start_block, 118 &offset)) 119 goto out; 120 SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); 121 } else 122 if (!squashfs_get_cached_block(s, (char *) &fragment_entry, 123 start_block, offset, 124 sizeof(fragment_entry), &start_block, 125 &offset)) 126 goto out; 127 128 *fragment_start_block = fragment_entry.start_block; 129 *fragment_size = fragment_entry.size; 130 131 return 1; 132 133 out: 134 return 0; 135 } 136 137 138 static struct inode *squashfs_new_inode(struct super_block *s, 139 struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) 140 { 141 struct squashfs_sb_info *msblk = s->s_fs_info; 142 struct squashfs_super_block *sblk = &msblk->sblk; 143 struct inode *i = new_inode(s); 144 145 if (i) { 146 i->i_ino = ino; 147 i->i_mtime.tv_sec = sblk->mkfs_time; 148 i->i_atime.tv_sec = sblk->mkfs_time; 149 i->i_ctime.tv_sec = sblk->mkfs_time; 150 i->i_uid = msblk->uid[inodeb->uid]; 151 i->i_mode = inodeb->mode; 152 i->i_nlink = 1; 153 i->i_size = 0; 154 if (inodeb->guid == SQUASHFS_GUIDS) 155 i->i_gid = i->i_uid; 156 else 157 i->i_gid = msblk->guid[inodeb->guid]; 158 } 159 160 return i; 161 } 162 163 164 static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode) 165 { 166 struct inode *i; 167 struct squashfs_sb_info *msblk = s->s_fs_info; 168 struct squashfs_super_block *sblk = &msblk->sblk; 169 unsigned int block = SQUASHFS_INODE_BLK(inode) + 170 sblk->inode_table_start; 171 unsigned int offset = SQUASHFS_INODE_OFFSET(inode); 172 unsigned int ino = SQUASHFS_MK_VFS_INODE(block 173 - sblk->inode_table_start, offset); 174 long long next_block; 175 unsigned int next_offset; 176 union squashfs_inode_header_2 id, sid; 177 struct squashfs_base_inode_header_2 *inodeb = &id.base, 178 *sinodeb = &sid.base; 179 180 TRACE("Entered squashfs_iget\n"); 181 182 if (msblk->swap) { 183 if (!squashfs_get_cached_block(s, (char *) sinodeb, block, 184 offset, sizeof(*sinodeb), &next_block, 185 &next_offset)) 186 goto failed_read; 187 SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, 188 sizeof(*sinodeb)); 189 } else 190 if (!squashfs_get_cached_block(s, (char *) inodeb, block, 191 offset, sizeof(*inodeb), &next_block, 192 &next_offset)) 193 goto failed_read; 194 195 switch(inodeb->inode_type) { 196 case SQUASHFS_FILE_TYPE: { 197 struct squashfs_reg_inode_header_2 *inodep = &id.reg; 198 struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; 199 long long frag_blk; 200 unsigned int frag_size; 201 202 if (msblk->swap) { 203 if (!squashfs_get_cached_block(s, (char *) 204 sinodep, block, offset, 205 sizeof(*sinodep), &next_block, 206 &next_offset)) 207 goto failed_read; 208 SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); 209 } else 210 if (!squashfs_get_cached_block(s, (char *) 211 inodep, block, offset, 212 sizeof(*inodep), &next_block, 213 &next_offset)) 214 goto failed_read; 215 216 frag_blk = SQUASHFS_INVALID_BLK; 217 if (inodep->fragment != SQUASHFS_INVALID_FRAG && 218 !get_fragment_location_2(s, 219 inodep->fragment, &frag_blk, &frag_size)) 220 goto failed_read; 221 222 if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 223 goto failed_read1; 224 225 i->i_size = inodep->file_size; 226 i->i_fop = &generic_ro_fops; 227 i->i_mode |= S_IFREG; 228 i->i_mtime.tv_sec = inodep->mtime; 229 i->i_atime.tv_sec = inodep->mtime; 230 i->i_ctime.tv_sec = inodep->mtime; 231 i->i_blocks = ((i->i_size - 1) >> 9) + 1; 232 SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; 233 SQUASHFS_I(i)->u.s1.fragment_size = frag_size; 234 SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; 235 SQUASHFS_I(i)->start_block = inodep->start_block; 236 SQUASHFS_I(i)->u.s1.block_list_start = next_block; 237 SQUASHFS_I(i)->offset = next_offset; 238 if (sblk->block_size > 4096) 239 i->i_data.a_ops = &squashfs_aops; 240 else 241 i->i_data.a_ops = &squashfs_aops_4K; 242 243 TRACE("File inode %x:%x, start_block %x, " 244 "block_list_start %llx, offset %x\n", 245 SQUASHFS_INODE_BLK(inode), offset, 246 inodep->start_block, next_block, 247 next_offset); 248 break; 249 } 250 case SQUASHFS_DIR_TYPE: { 251 struct squashfs_dir_inode_header_2 *inodep = &id.dir; 252 struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; 253 254 if (msblk->swap) { 255 if (!squashfs_get_cached_block(s, (char *) 256 sinodep, block, offset, 257 sizeof(*sinodep), &next_block, 258 &next_offset)) 259 goto failed_read; 260 SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); 261 } else 262 if (!squashfs_get_cached_block(s, (char *) 263 inodep, block, offset, 264 sizeof(*inodep), &next_block, 265 &next_offset)) 266 goto failed_read; 267 268 if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 269 goto failed_read1; 270 271 i->i_size = inodep->file_size; 272 i->i_op = &squashfs_dir_inode_ops_2; 273 i->i_fop = &squashfs_dir_ops_2; 274 i->i_mode |= S_IFDIR; 275 i->i_mtime.tv_sec = inodep->mtime; 276 i->i_atime.tv_sec = inodep->mtime; 277 i->i_ctime.tv_sec = inodep->mtime; 278 SQUASHFS_I(i)->start_block = inodep->start_block; 279 SQUASHFS_I(i)->offset = inodep->offset; 280 SQUASHFS_I(i)->u.s2.directory_index_count = 0; 281 SQUASHFS_I(i)->u.s2.parent_inode = 0; 282 283 TRACE("Directory inode %x:%x, start_block %x, offset " 284 "%x\n", SQUASHFS_INODE_BLK(inode), 285 offset, inodep->start_block, 286 inodep->offset); 287 break; 288 } 289 case SQUASHFS_LDIR_TYPE: { 290 struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; 291 struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; 292 293 if (msblk->swap) { 294 if (!squashfs_get_cached_block(s, (char *) 295 sinodep, block, offset, 296 sizeof(*sinodep), &next_block, 297 &next_offset)) 298 goto failed_read; 299 SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, 300 sinodep); 301 } else 302 if (!squashfs_get_cached_block(s, (char *) 303 inodep, block, offset, 304 sizeof(*inodep), &next_block, 305 &next_offset)) 306 goto failed_read; 307 308 if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 309 goto failed_read1; 310 311 i->i_size = inodep->file_size; 312 i->i_op = &squashfs_dir_inode_ops_2; 313 i->i_fop = &squashfs_dir_ops_2; 314 i->i_mode |= S_IFDIR; 315 i->i_mtime.tv_sec = inodep->mtime; 316 i->i_atime.tv_sec = inodep->mtime; 317 i->i_ctime.tv_sec = inodep->mtime; 318 SQUASHFS_I(i)->start_block = inodep->start_block; 319 SQUASHFS_I(i)->offset = inodep->offset; 320 SQUASHFS_I(i)->u.s2.directory_index_start = next_block; 321 SQUASHFS_I(i)->u.s2.directory_index_offset = 322 next_offset; 323 SQUASHFS_I(i)->u.s2.directory_index_count = 324 inodep->i_count; 325 SQUASHFS_I(i)->u.s2.parent_inode = 0; 326 327 TRACE("Long directory inode %x:%x, start_block %x, " 328 "offset %x\n", 329 SQUASHFS_INODE_BLK(inode), offset, 330 inodep->start_block, inodep->offset); 331 break; 332 } 333 case SQUASHFS_SYMLINK_TYPE: { 334 struct squashfs_symlink_inode_header_2 *inodep = 335 &id.symlink; 336 struct squashfs_symlink_inode_header_2 *sinodep = 337 &sid.symlink; 338 339 if (msblk->swap) { 340 if (!squashfs_get_cached_block(s, (char *) 341 sinodep, block, offset, 342 sizeof(*sinodep), &next_block, 343 &next_offset)) 344 goto failed_read; 345 SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, 346 sinodep); 347 } else 348 if (!squashfs_get_cached_block(s, (char *) 349 inodep, block, offset, 350 sizeof(*inodep), &next_block, 351 &next_offset)) 352 goto failed_read; 353 354 if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 355 goto failed_read1; 356 357 i->i_size = inodep->symlink_size; 358 i->i_op = &page_symlink_inode_operations; 359 i->i_data.a_ops = &squashfs_symlink_aops; 360 i->i_mode |= S_IFLNK; 361 SQUASHFS_I(i)->start_block = next_block; 362 SQUASHFS_I(i)->offset = next_offset; 363 364 TRACE("Symbolic link inode %x:%x, start_block %llx, " 365 "offset %x\n", 366 SQUASHFS_INODE_BLK(inode), offset, 367 next_block, next_offset); 368 break; 369 } 370 case SQUASHFS_BLKDEV_TYPE: 371 case SQUASHFS_CHRDEV_TYPE: { 372 struct squashfs_dev_inode_header_2 *inodep = &id.dev; 373 struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; 374 375 if (msblk->swap) { 376 if (!squashfs_get_cached_block(s, (char *) 377 sinodep, block, offset, 378 sizeof(*sinodep), &next_block, 379 &next_offset)) 380 goto failed_read; 381 SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); 382 } else 383 if (!squashfs_get_cached_block(s, (char *) 384 inodep, block, offset, 385 sizeof(*inodep), &next_block, 386 &next_offset)) 387 goto failed_read; 388 389 if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 390 goto failed_read1; 391 392 i->i_mode |= (inodeb->inode_type == 393 SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : 394 S_IFBLK; 395 init_special_inode(i, i->i_mode, 396 old_decode_dev(inodep->rdev)); 397 398 TRACE("Device inode %x:%x, rdev %x\n", 399 SQUASHFS_INODE_BLK(inode), offset, 400 inodep->rdev); 401 break; 402 } 403 case SQUASHFS_FIFO_TYPE: 404 case SQUASHFS_SOCKET_TYPE: { 405 if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) 406 goto failed_read1; 407 408 i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) 409 ? S_IFIFO : S_IFSOCK; 410 init_special_inode(i, i->i_mode, 0); 411 break; 412 } 413 default: 414 ERROR("Unknown inode type %d in squashfs_iget!\n", 415 inodeb->inode_type); 416 goto failed_read1; 417 } 418 419 insert_inode_hash(i); 420 return i; 421 422 failed_read: 423 ERROR("Unable to read inode [%x:%x]\n", block, offset); 424 425 failed_read1: 426 return NULL; 427 } 428 429 430 static int get_dir_index_using_offset(struct super_block *s, long long 431 *next_block, unsigned int *next_offset, 432 long long index_start, 433 unsigned int index_offset, int i_count, 434 long long f_pos) 435 { 436 struct squashfs_sb_info *msblk = s->s_fs_info; 437 struct squashfs_super_block *sblk = &msblk->sblk; 438 int i, length = 0; 439 struct squashfs_dir_index_2 index; 440 441 TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", 442 i_count, (unsigned int) f_pos); 443 444 if (f_pos == 0) 445 goto finish; 446 447 for (i = 0; i < i_count; i++) { 448 if (msblk->swap) { 449 struct squashfs_dir_index_2 sindex; 450 squashfs_get_cached_block(s, (char *) &sindex, 451 index_start, index_offset, 452 sizeof(sindex), &index_start, 453 &index_offset); 454 SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); 455 } else 456 squashfs_get_cached_block(s, (char *) &index, 457 index_start, index_offset, 458 sizeof(index), &index_start, 459 &index_offset); 460 461 if (index.index > f_pos) 462 break; 463 464 squashfs_get_cached_block(s, NULL, index_start, index_offset, 465 index.size + 1, &index_start, 466 &index_offset); 467 468 length = index.index; 469 *next_block = index.start_block + sblk->directory_table_start; 470 } 471 472 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 473 474 finish: 475 return length; 476 } 477 478 479 static int get_dir_index_using_name(struct super_block *s, long long 480 *next_block, unsigned int *next_offset, 481 long long index_start, 482 unsigned int index_offset, int i_count, 483 const char *name, int size) 484 { 485 struct squashfs_sb_info *msblk = s->s_fs_info; 486 struct squashfs_super_block *sblk = &msblk->sblk; 487 int i, length = 0; 488 struct squashfs_dir_index_2 *index; 489 char *str; 490 491 TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); 492 493 if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + 494 (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { 495 ERROR("Failed to allocate squashfs_dir_index\n"); 496 goto failure; 497 } 498 499 index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); 500 strncpy(str, name, size); 501 str[size] = '\0'; 502 503 for (i = 0; i < i_count; i++) { 504 if (msblk->swap) { 505 struct squashfs_dir_index_2 sindex; 506 squashfs_get_cached_block(s, (char *) &sindex, 507 index_start, index_offset, 508 sizeof(sindex), &index_start, 509 &index_offset); 510 SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); 511 } else 512 squashfs_get_cached_block(s, (char *) index, 513 index_start, index_offset, 514 sizeof(struct squashfs_dir_index_2), 515 &index_start, &index_offset); 516 517 squashfs_get_cached_block(s, index->name, index_start, 518 index_offset, index->size + 1, 519 &index_start, &index_offset); 520 521 index->name[index->size + 1] = '\0'; 522 523 if (strcmp(index->name, str) > 0) 524 break; 525 526 length = index->index; 527 *next_block = index->start_block + sblk->directory_table_start; 528 } 529 530 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 531 kfree(str); 532 failure: 533 return length; 534 } 535 536 537 static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) 538 { 539 struct inode *i = file->f_dentry->d_inode; 540 struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; 541 struct squashfs_super_block *sblk = &msblk->sblk; 542 long long next_block = SQUASHFS_I(i)->start_block + 543 sblk->directory_table_start; 544 int next_offset = SQUASHFS_I(i)->offset, length = 0, 545 dir_count; 546 struct squashfs_dir_header_2 dirh; 547 struct squashfs_dir_entry_2 *dire; 548 549 TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); 550 551 if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + 552 SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { 553 ERROR("Failed to allocate squashfs_dir_entry\n"); 554 goto finish; 555 } 556 557 length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, 558 SQUASHFS_I(i)->u.s2.directory_index_start, 559 SQUASHFS_I(i)->u.s2.directory_index_offset, 560 SQUASHFS_I(i)->u.s2.directory_index_count, 561 file->f_pos); 562 563 while (length < i_size_read(i)) { 564 /* read directory header */ 565 if (msblk->swap) { 566 struct squashfs_dir_header_2 sdirh; 567 568 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 569 next_block, next_offset, sizeof(sdirh), 570 &next_block, &next_offset)) 571 goto failed_read; 572 573 length += sizeof(sdirh); 574 SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); 575 } else { 576 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 577 next_block, next_offset, sizeof(dirh), 578 &next_block, &next_offset)) 579 goto failed_read; 580 581 length += sizeof(dirh); 582 } 583 584 dir_count = dirh.count + 1; 585 while (dir_count--) { 586 if (msblk->swap) { 587 struct squashfs_dir_entry_2 sdire; 588 if (!squashfs_get_cached_block(i->i_sb, (char *) 589 &sdire, next_block, next_offset, 590 sizeof(sdire), &next_block, 591 &next_offset)) 592 goto failed_read; 593 594 length += sizeof(sdire); 595 SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); 596 } else { 597 if (!squashfs_get_cached_block(i->i_sb, (char *) 598 dire, next_block, next_offset, 599 sizeof(*dire), &next_block, 600 &next_offset)) 601 goto failed_read; 602 603 length += sizeof(*dire); 604 } 605 606 if (!squashfs_get_cached_block(i->i_sb, dire->name, 607 next_block, next_offset, 608 dire->size + 1, &next_block, 609 &next_offset)) 610 goto failed_read; 611 612 length += dire->size + 1; 613 614 if (file->f_pos >= length) 615 continue; 616 617 dire->name[dire->size + 1] = '\0'; 618 619 TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", 620 (unsigned int) dirent, dire->name, 621 dire->size + 1, (int) file->f_pos, 622 dirh.start_block, dire->offset, 623 squashfs_filetype_table[dire->type]); 624 625 if (filldir(dirent, dire->name, dire->size + 1, 626 file->f_pos, SQUASHFS_MK_VFS_INODE( 627 dirh.start_block, dire->offset), 628 squashfs_filetype_table[dire->type]) 629 < 0) { 630 TRACE("Filldir returned less than 0\n"); 631 goto finish; 632 } 633 file->f_pos = length; 634 } 635 } 636 637 finish: 638 kfree(dire); 639 return 0; 640 641 failed_read: 642 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 643 next_offset); 644 kfree(dire); 645 return 0; 646 } 647 648 649 static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, 650 struct nameidata *nd) 651 { 652 const unsigned char *name = dentry->d_name.name; 653 int len = dentry->d_name.len; 654 struct inode *inode = NULL; 655 struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; 656 struct squashfs_super_block *sblk = &msblk->sblk; 657 long long next_block = SQUASHFS_I(i)->start_block + 658 sblk->directory_table_start; 659 int next_offset = SQUASHFS_I(i)->offset, length = 0, 660 dir_count; 661 struct squashfs_dir_header_2 dirh; 662 struct squashfs_dir_entry_2 *dire; 663 int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; 664 665 TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); 666 667 if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + 668 SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { 669 ERROR("Failed to allocate squashfs_dir_entry\n"); 670 goto exit_loop; 671 } 672 673 if (len > SQUASHFS_NAME_LEN) 674 goto exit_loop; 675 676 length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, 677 SQUASHFS_I(i)->u.s2.directory_index_start, 678 SQUASHFS_I(i)->u.s2.directory_index_offset, 679 SQUASHFS_I(i)->u.s2.directory_index_count, name, 680 len); 681 682 while (length < i_size_read(i)) { 683 /* read directory header */ 684 if (msblk->swap) { 685 struct squashfs_dir_header_2 sdirh; 686 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 687 next_block, next_offset, sizeof(sdirh), 688 &next_block, &next_offset)) 689 goto failed_read; 690 691 length += sizeof(sdirh); 692 SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); 693 } else { 694 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 695 next_block, next_offset, sizeof(dirh), 696 &next_block, &next_offset)) 697 goto failed_read; 698 699 length += sizeof(dirh); 700 } 701 702 dir_count = dirh.count + 1; 703 while (dir_count--) { 704 if (msblk->swap) { 705 struct squashfs_dir_entry_2 sdire; 706 if (!squashfs_get_cached_block(i->i_sb, (char *) 707 &sdire, next_block,next_offset, 708 sizeof(sdire), &next_block, 709 &next_offset)) 710 goto failed_read; 711 712 length += sizeof(sdire); 713 SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); 714 } else { 715 if (!squashfs_get_cached_block(i->i_sb, (char *) 716 dire, next_block,next_offset, 717 sizeof(*dire), &next_block, 718 &next_offset)) 719 goto failed_read; 720 721 length += sizeof(*dire); 722 } 723 724 if (!squashfs_get_cached_block(i->i_sb, dire->name, 725 next_block, next_offset, dire->size + 1, 726 &next_block, &next_offset)) 727 goto failed_read; 728 729 length += dire->size + 1; 730 731 if (sorted && name[0] < dire->name[0]) 732 goto exit_loop; 733 734 if ((len == dire->size + 1) && !strncmp(name, 735 dire->name, len)) { 736 squashfs_inode_t ino = 737 SQUASHFS_MKINODE(dirh.start_block, 738 dire->offset); 739 740 TRACE("calling squashfs_iget for directory " 741 "entry %s, inode %x:%x, %lld\n", name, 742 dirh.start_block, dire->offset, ino); 743 744 inode = (msblk->iget)(i->i_sb, ino); 745 746 goto exit_loop; 747 } 748 } 749 } 750 751 exit_loop: 752 kfree(dire); 753 d_add(dentry, inode); 754 return ERR_PTR(0); 755 756 failed_read: 757 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 758 next_offset); 759 goto exit_loop; 760 } 761 762 763 int squashfs_2_0_supported(struct squashfs_sb_info *msblk) 764 { 765 struct squashfs_super_block *sblk = &msblk->sblk; 766 767 msblk->iget = squashfs_iget_2; 768 msblk->read_fragment_index_table = read_fragment_index_table_2; 769 770 sblk->bytes_used = sblk->bytes_used_2; 771 sblk->uid_start = sblk->uid_start_2; 772 sblk->guid_start = sblk->guid_start_2; 773 sblk->inode_table_start = sblk->inode_table_start_2; 774 sblk->directory_table_start = sblk->directory_table_start_2; 775 sblk->fragment_table_start = sblk->fragment_table_start_2; 776 777 return 1; 778 } -
include/linux/squashfs_fs.h
diff -Nru linux-2.6.19.ori2/include/linux/squashfs_fs.h linux-2.6.19.ori/include/linux/squashfs_fs.h
old new 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@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 #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE 39 #define SQUASHFS_MAJOR 3 40 #define SQUASHFS_MINOR 0 41 #define SQUASHFS_MAGIC 0x73717368 42 #define SQUASHFS_MAGIC_SWAP 0x68737173 43 #define SQUASHFS_START 0 44 45 /* size of metadata (inode and directory) blocks */ 46 #define SQUASHFS_METADATA_SIZE 8192 47 #define SQUASHFS_METADATA_LOG 13 48 49 /* default size of data blocks */ 50 #define SQUASHFS_FILE_SIZE 65536 51 #define SQUASHFS_FILE_LOG 16 52 53 #define SQUASHFS_FILE_MAX_SIZE 65536 54 55 /* Max number of uids and gids */ 56 #define SQUASHFS_UIDS 256 57 #define SQUASHFS_GUIDS 255 58 59 /* Max length of filename (not 255) */ 60 #define SQUASHFS_NAME_LEN 256 61 62 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) 63 #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) 64 #define SQUASHFS_INVALID_BLK ((long long) -1) 65 #define SQUASHFS_USED_BLK ((long long) -2) 66 67 /* Filesystem flags */ 68 #define SQUASHFS_NOI 0 69 #define SQUASHFS_NOD 1 70 #define SQUASHFS_CHECK 2 71 #define SQUASHFS_NOF 3 72 #define SQUASHFS_NO_FRAG 4 73 #define SQUASHFS_ALWAYS_FRAG 5 74 #define SQUASHFS_DUPLICATE 6 75 76 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) 77 78 #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ 79 SQUASHFS_NOI) 80 81 #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ 82 SQUASHFS_NOD) 83 84 #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ 85 SQUASHFS_NOF) 86 87 #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ 88 SQUASHFS_NO_FRAG) 89 90 #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ 91 SQUASHFS_ALWAYS_FRAG) 92 93 #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ 94 SQUASHFS_DUPLICATE) 95 96 #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ 97 SQUASHFS_CHECK) 98 99 #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ 100 duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ 101 | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ 102 (duplicate_checking << 6)) 103 104 /* Max number of types and file types */ 105 #define SQUASHFS_DIR_TYPE 1 106 #define SQUASHFS_FILE_TYPE 2 107 #define SQUASHFS_SYMLINK_TYPE 3 108 #define SQUASHFS_BLKDEV_TYPE 4 109 #define SQUASHFS_CHRDEV_TYPE 5 110 #define SQUASHFS_FIFO_TYPE 6 111 #define SQUASHFS_SOCKET_TYPE 7 112 #define SQUASHFS_LDIR_TYPE 8 113 #define SQUASHFS_LREG_TYPE 9 114 115 /* 1.0 filesystem type definitions */ 116 #define SQUASHFS_TYPES 5 117 #define SQUASHFS_IPC_TYPE 0 118 119 /* Flag whether block is compressed or uncompressed, bit is set if block is 120 * uncompressed */ 121 #define SQUASHFS_COMPRESSED_BIT (1 << 15) 122 123 #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ 124 (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) 125 126 #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) 127 128 #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) 129 130 #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ 131 ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ 132 ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) 133 134 #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) 135 136 /* 137 * Inode number ops. Inodes consist of a compressed block number, and an 138 * uncompressed offset within that block 139 */ 140 #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) 141 142 #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) 143 144 #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ 145 << 16) + (B))) 146 147 /* Compute 32 bit VFS inode number from squashfs inode number */ 148 #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ 149 ((b) >> 2) + 1)) 150 /* XXX */ 151 152 /* Translate between VFS mode and squashfs mode */ 153 #define SQUASHFS_MODE(a) ((a) & 0xfff) 154 155 /* fragment and fragment table defines */ 156 #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) 157 158 #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ 159 SQUASHFS_METADATA_SIZE) 160 161 #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ 162 SQUASHFS_METADATA_SIZE) 163 164 #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ 165 SQUASHFS_METADATA_SIZE - 1) / \ 166 SQUASHFS_METADATA_SIZE) 167 168 #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ 169 sizeof(long long)) 170 171 /* cached data constants for filesystem */ 172 #define SQUASHFS_CACHED_BLKS 8 173 174 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 175 176 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ 177 (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) 178 179 #define SQUASHFS_MARKER_BYTE 0xff 180 181 /* meta index cache */ 182 #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) 183 #define SQUASHFS_META_ENTRIES 31 184 #define SQUASHFS_META_NUMBER 8 185 #define SQUASHFS_SLOTS 4 186 187 struct meta_entry { 188 long long data_block; 189 unsigned int index_block; 190 unsigned short offset; 191 unsigned short pad; 192 }; 193 194 struct meta_index { 195 unsigned int inode_number; 196 unsigned int offset; 197 unsigned short entries; 198 unsigned short skip; 199 unsigned short locked; 200 unsigned short pad; 201 struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; 202 }; 203 204 205 /* 206 * definitions for structures on disk 207 */ 208 209 typedef long long squashfs_block_t; 210 typedef long long squashfs_inode_t; 211 212 struct squashfs_super_block { 213 unsigned int s_magic; 214 unsigned int inodes; 215 unsigned int bytes_used_2; 216 unsigned int uid_start_2; 217 unsigned int guid_start_2; 218 unsigned int inode_table_start_2; 219 unsigned int directory_table_start_2; 220 unsigned int s_major:16; 221 unsigned int s_minor:16; 222 unsigned int block_size_1:16; 223 unsigned int block_log:16; 224 unsigned int flags:8; 225 unsigned int no_uids:8; 226 unsigned int no_guids:8; 227 unsigned int mkfs_time /* time of filesystem creation */; 228 squashfs_inode_t root_inode; 229 unsigned int block_size; 230 unsigned int fragments; 231 unsigned int fragment_table_start_2; 232 long long bytes_used; 233 long long uid_start; 234 long long guid_start; 235 long long inode_table_start; 236 long long directory_table_start; 237 long long fragment_table_start; 238 long long unused; 239 } __attribute__ ((packed)); 240 241 struct squashfs_dir_index { 242 unsigned int index; 243 unsigned int start_block; 244 unsigned char size; 245 unsigned char name[0]; 246 } __attribute__ ((packed)); 247 248 #define SQUASHFS_BASE_INODE_HEADER \ 249 unsigned int inode_type:4; \ 250 unsigned int mode:12; \ 251 unsigned int uid:8; \ 252 unsigned int guid:8; \ 253 unsigned int mtime; \ 254 unsigned int inode_number; 255 256 struct squashfs_base_inode_header { 257 SQUASHFS_BASE_INODE_HEADER; 258 } __attribute__ ((packed)); 259 260 struct squashfs_ipc_inode_header { 261 SQUASHFS_BASE_INODE_HEADER; 262 unsigned int nlink; 263 } __attribute__ ((packed)); 264 265 struct squashfs_dev_inode_header { 266 SQUASHFS_BASE_INODE_HEADER; 267 unsigned int nlink; 268 unsigned short rdev; 269 } __attribute__ ((packed)); 270 271 struct squashfs_symlink_inode_header { 272 SQUASHFS_BASE_INODE_HEADER; 273 unsigned int nlink; 274 unsigned short symlink_size; 275 char symlink[0]; 276 } __attribute__ ((packed)); 277 278 struct squashfs_reg_inode_header { 279 SQUASHFS_BASE_INODE_HEADER; 280 squashfs_block_t start_block; 281 unsigned int fragment; 282 unsigned int offset; 283 unsigned int file_size; 284 unsigned short block_list[0]; 285 } __attribute__ ((packed)); 286 287 struct squashfs_lreg_inode_header { 288 SQUASHFS_BASE_INODE_HEADER; 289 unsigned int nlink; 290 squashfs_block_t start_block; 291 unsigned int fragment; 292 unsigned int offset; 293 long long file_size; 294 unsigned short block_list[0]; 295 } __attribute__ ((packed)); 296 297 struct squashfs_dir_inode_header { 298 SQUASHFS_BASE_INODE_HEADER; 299 unsigned int nlink; 300 unsigned int file_size:19; 301 unsigned int offset:13; 302 unsigned int start_block; 303 unsigned int parent_inode; 304 } __attribute__ ((packed)); 305 306 struct squashfs_ldir_inode_header { 307 SQUASHFS_BASE_INODE_HEADER; 308 unsigned int nlink; 309 unsigned int file_size:27; 310 unsigned int offset:13; 311 unsigned int start_block; 312 unsigned int i_count:16; 313 unsigned int parent_inode; 314 struct squashfs_dir_index index[0]; 315 } __attribute__ ((packed)); 316 317 union squashfs_inode_header { 318 struct squashfs_base_inode_header base; 319 struct squashfs_dev_inode_header dev; 320 struct squashfs_symlink_inode_header symlink; 321 struct squashfs_reg_inode_header reg; 322 struct squashfs_lreg_inode_header lreg; 323 struct squashfs_dir_inode_header dir; 324 struct squashfs_ldir_inode_header ldir; 325 struct squashfs_ipc_inode_header ipc; 326 }; 327 328 struct squashfs_dir_entry { 329 unsigned int offset:13; 330 unsigned int type:3; 331 unsigned int size:8; 332 int inode_number:16; 333 char name[0]; 334 } __attribute__ ((packed)); 335 336 struct squashfs_dir_header { 337 unsigned int count:8; 338 unsigned int start_block; 339 unsigned int inode_number; 340 } __attribute__ ((packed)); 341 342 struct squashfs_fragment_entry { 343 long long start_block; 344 unsigned int size; 345 unsigned int unused; 346 } __attribute__ ((packed)); 347 348 extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); 349 extern int squashfs_uncompress_init(void); 350 extern int squashfs_uncompress_exit(void); 351 352 /* 353 * macros to convert each packed bitfield structure from little endian to big 354 * endian and vice versa. These are needed when creating or using a filesystem 355 * on a machine with different byte ordering to the target architecture. 356 * 357 */ 358 359 #define SQUASHFS_SWAP_START \ 360 int bits;\ 361 int b_pos;\ 362 unsigned long long val;\ 363 unsigned char *s;\ 364 unsigned char *d; 365 366 #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ 367 SQUASHFS_SWAP_START\ 368 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ 369 SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ 370 SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ 371 SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ 372 SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ 373 SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ 374 SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ 375 SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ 376 SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ 377 SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ 378 SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ 379 SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ 380 SQUASHFS_SWAP((s)->flags, d, 288, 8);\ 381 SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ 382 SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ 383 SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ 384 SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ 385 SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ 386 SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ 387 SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ 388 SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ 389 SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ 390 SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ 391 SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ 392 SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ 393 SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ 394 SQUASHFS_SWAP((s)->unused, d, 888, 64);\ 395 } 396 397 #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ 398 SQUASHFS_MEMSET(s, d, n);\ 399 SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ 400 SQUASHFS_SWAP((s)->mode, d, 4, 12);\ 401 SQUASHFS_SWAP((s)->uid, d, 16, 8);\ 402 SQUASHFS_SWAP((s)->guid, d, 24, 8);\ 403 SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ 404 SQUASHFS_SWAP((s)->inode_number, d, 64, 32); 405 406 #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ 407 SQUASHFS_SWAP_START\ 408 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ 409 } 410 411 #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ 412 SQUASHFS_SWAP_START\ 413 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 414 sizeof(struct squashfs_ipc_inode_header))\ 415 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 416 } 417 418 #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ 419 SQUASHFS_SWAP_START\ 420 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 421 sizeof(struct squashfs_dev_inode_header)); \ 422 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 423 SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ 424 } 425 426 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ 427 SQUASHFS_SWAP_START\ 428 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 429 sizeof(struct squashfs_symlink_inode_header));\ 430 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 431 SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ 432 } 433 434 #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ 435 SQUASHFS_SWAP_START\ 436 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 437 sizeof(struct squashfs_reg_inode_header));\ 438 SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ 439 SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ 440 SQUASHFS_SWAP((s)->offset, d, 192, 32);\ 441 SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ 442 } 443 444 #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ 445 SQUASHFS_SWAP_START\ 446 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 447 sizeof(struct squashfs_lreg_inode_header));\ 448 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 449 SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ 450 SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ 451 SQUASHFS_SWAP((s)->offset, d, 224, 32);\ 452 SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ 453 } 454 455 #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ 456 SQUASHFS_SWAP_START\ 457 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 458 sizeof(struct squashfs_dir_inode_header));\ 459 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 460 SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ 461 SQUASHFS_SWAP((s)->offset, d, 147, 13);\ 462 SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ 463 SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ 464 } 465 466 #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ 467 SQUASHFS_SWAP_START\ 468 SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ 469 sizeof(struct squashfs_ldir_inode_header));\ 470 SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ 471 SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ 472 SQUASHFS_SWAP((s)->offset, d, 155, 13);\ 473 SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ 474 SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ 475 SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ 476 } 477 478 #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ 479 SQUASHFS_SWAP_START\ 480 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ 481 SQUASHFS_SWAP((s)->index, d, 0, 32);\ 482 SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ 483 SQUASHFS_SWAP((s)->size, d, 64, 8);\ 484 } 485 486 #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ 487 SQUASHFS_SWAP_START\ 488 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ 489 SQUASHFS_SWAP((s)->count, d, 0, 8);\ 490 SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ 491 SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ 492 } 493 494 #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ 495 SQUASHFS_SWAP_START\ 496 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ 497 SQUASHFS_SWAP((s)->offset, d, 0, 13);\ 498 SQUASHFS_SWAP((s)->type, d, 13, 3);\ 499 SQUASHFS_SWAP((s)->size, d, 16, 8);\ 500 SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ 501 } 502 503 #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ 504 SQUASHFS_SWAP_START\ 505 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ 506 SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ 507 SQUASHFS_SWAP((s)->size, d, 64, 32);\ 508 } 509 510 #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ 511 int entry;\ 512 int bit_position;\ 513 SQUASHFS_SWAP_START\ 514 SQUASHFS_MEMSET(s, d, n * 2);\ 515 for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 516 16)\ 517 SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ 518 } 519 520 #define SQUASHFS_SWAP_INTS(s, d, n) {\ 521 int entry;\ 522 int bit_position;\ 523 SQUASHFS_SWAP_START\ 524 SQUASHFS_MEMSET(s, d, n * 4);\ 525 for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 526 32)\ 527 SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ 528 } 529 530 #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ 531 int entry;\ 532 int bit_position;\ 533 SQUASHFS_SWAP_START\ 534 SQUASHFS_MEMSET(s, d, n * 8);\ 535 for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 536 64)\ 537 SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ 538 } 539 540 #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ 541 int entry;\ 542 int bit_position;\ 543 SQUASHFS_SWAP_START\ 544 SQUASHFS_MEMSET(s, d, n * bits / 8);\ 545 for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 546 bits)\ 547 SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ 548 } 549 550 #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) 551 552 #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY 553 554 struct squashfs_base_inode_header_1 { 555 unsigned int inode_type:4; 556 unsigned int mode:12; /* protection */ 557 unsigned int uid:4; /* index into uid table */ 558 unsigned int guid:4; /* index into guid table */ 559 } __attribute__ ((packed)); 560 561 struct squashfs_ipc_inode_header_1 { 562 unsigned int inode_type:4; 563 unsigned int mode:12; /* protection */ 564 unsigned int uid:4; /* index into uid table */ 565 unsigned int guid:4; /* index into guid table */ 566 unsigned int type:4; 567 unsigned int offset:4; 568 } __attribute__ ((packed)); 569 570 struct squashfs_dev_inode_header_1 { 571 unsigned int inode_type:4; 572 unsigned int mode:12; /* protection */ 573 unsigned int uid:4; /* index into uid table */ 574 unsigned int guid:4; /* index into guid table */ 575 unsigned short rdev; 576 } __attribute__ ((packed)); 577 578 struct squashfs_symlink_inode_header_1 { 579 unsigned int inode_type:4; 580 unsigned int mode:12; /* protection */ 581 unsigned int uid:4; /* index into uid table */ 582 unsigned int guid:4; /* index into guid table */ 583 unsigned short symlink_size; 584 char symlink[0]; 585 } __attribute__ ((packed)); 586 587 struct squashfs_reg_inode_header_1 { 588 unsigned int inode_type:4; 589 unsigned int mode:12; /* protection */ 590 unsigned int uid:4; /* index into uid table */ 591 unsigned int guid:4; /* index into guid table */ 592 unsigned int mtime; 593 unsigned int start_block; 594 unsigned int file_size:32; 595 unsigned short block_list[0]; 596 } __attribute__ ((packed)); 597 598 struct squashfs_dir_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 int file_size:19; 604 unsigned int offset:13; 605 unsigned int mtime; 606 unsigned int start_block:24; 607 } __attribute__ ((packed)); 608 609 #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ 610 SQUASHFS_MEMSET(s, d, n);\ 611 SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ 612 SQUASHFS_SWAP((s)->mode, d, 4, 12);\ 613 SQUASHFS_SWAP((s)->uid, d, 16, 4);\ 614 SQUASHFS_SWAP((s)->guid, d, 20, 4); 615 616 #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ 617 SQUASHFS_SWAP_START\ 618 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ 619 } 620 621 #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ 622 SQUASHFS_SWAP_START\ 623 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ 624 sizeof(struct squashfs_ipc_inode_header_1));\ 625 SQUASHFS_SWAP((s)->type, d, 24, 4);\ 626 SQUASHFS_SWAP((s)->offset, d, 28, 4);\ 627 } 628 629 #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ 630 SQUASHFS_SWAP_START\ 631 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ 632 sizeof(struct squashfs_dev_inode_header_1));\ 633 SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ 634 } 635 636 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ 637 SQUASHFS_SWAP_START\ 638 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ 639 sizeof(struct squashfs_symlink_inode_header_1));\ 640 SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ 641 } 642 643 #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ 644 SQUASHFS_SWAP_START\ 645 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ 646 sizeof(struct squashfs_reg_inode_header_1));\ 647 SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ 648 SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ 649 SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ 650 } 651 652 #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ 653 SQUASHFS_SWAP_START\ 654 SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ 655 sizeof(struct squashfs_dir_inode_header_1));\ 656 SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ 657 SQUASHFS_SWAP((s)->offset, d, 43, 13);\ 658 SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ 659 SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ 660 } 661 662 #endif 663 664 #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY 665 666 struct squashfs_dir_index_2 { 667 unsigned int index:27; 668 unsigned int start_block:29; 669 unsigned char size; 670 unsigned char name[0]; 671 } __attribute__ ((packed)); 672 673 struct squashfs_base_inode_header_2 { 674 unsigned int inode_type:4; 675 unsigned int mode:12; /* protection */ 676 unsigned int uid:8; /* index into uid table */ 677 unsigned int guid:8; /* index into guid table */ 678 } __attribute__ ((packed)); 679 680 struct squashfs_ipc_inode_header_2 { 681 unsigned int inode_type:4; 682 unsigned int mode:12; /* protection */ 683 unsigned int uid:8; /* index into uid table */ 684 unsigned int guid:8; /* index into guid table */ 685 } __attribute__ ((packed)); 686 687 struct squashfs_dev_inode_header_2 { 688 unsigned int inode_type:4; 689 unsigned int mode:12; /* protection */ 690 unsigned int uid:8; /* index into uid table */ 691 unsigned int guid:8; /* index into guid table */ 692 unsigned short rdev; 693 } __attribute__ ((packed)); 694 695 struct squashfs_symlink_inode_header_2 { 696 unsigned int inode_type:4; 697 unsigned int mode:12; /* protection */ 698 unsigned int uid:8; /* index into uid table */ 699 unsigned int guid:8; /* index into guid table */ 700 unsigned short symlink_size; 701 char symlink[0]; 702 } __attribute__ ((packed)); 703 704 struct squashfs_reg_inode_header_2 { 705 unsigned int inode_type:4; 706 unsigned int mode:12; /* protection */ 707 unsigned int uid:8; /* index into uid table */ 708 unsigned int guid:8; /* index into guid table */ 709 unsigned int mtime; 710 unsigned int start_block; 711 unsigned int fragment; 712 unsigned int offset; 713 unsigned int file_size:32; 714 unsigned short block_list[0]; 715 } __attribute__ ((packed)); 716 717 struct squashfs_dir_inode_header_2 { 718 unsigned int inode_type:4; 719 unsigned int mode:12; /* protection */ 720 unsigned int uid:8; /* index into uid table */ 721 unsigned int guid:8; /* index into guid table */ 722 unsigned int file_size:19; 723 unsigned int offset:13; 724 unsigned int mtime; 725 unsigned int start_block:24; 726 } __attribute__ ((packed)); 727 728 struct squashfs_ldir_inode_header_2 { 729 unsigned int inode_type:4; 730 unsigned int mode:12; /* protection */ 731 unsigned int uid:8; /* index into uid table */ 732 unsigned int guid:8; /* index into guid table */ 733 unsigned int file_size:27; 734 unsigned int offset:13; 735 unsigned int mtime; 736 unsigned int start_block:24; 737 unsigned int i_count:16; 738 struct squashfs_dir_index_2 index[0]; 739 } __attribute__ ((packed)); 740 741 union squashfs_inode_header_2 { 742 struct squashfs_base_inode_header_2 base; 743 struct squashfs_dev_inode_header_2 dev; 744 struct squashfs_symlink_inode_header_2 symlink; 745 struct squashfs_reg_inode_header_2 reg; 746 struct squashfs_dir_inode_header_2 dir; 747 struct squashfs_ldir_inode_header_2 ldir; 748 struct squashfs_ipc_inode_header_2 ipc; 749 }; 750 751 struct squashfs_dir_header_2 { 752 unsigned int count:8; 753 unsigned int start_block:24; 754 } __attribute__ ((packed)); 755 756 struct squashfs_dir_entry_2 { 757 unsigned int offset:13; 758 unsigned int type:3; 759 unsigned int size:8; 760 char name[0]; 761 } __attribute__ ((packed)); 762 763 struct squashfs_fragment_entry_2 { 764 unsigned int start_block; 765 unsigned int size; 766 } __attribute__ ((packed)); 767 768 #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ 769 SQUASHFS_MEMSET(s, d, n);\ 770 SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ 771 SQUASHFS_SWAP((s)->mode, d, 4, 12);\ 772 SQUASHFS_SWAP((s)->uid, d, 16, 8);\ 773 SQUASHFS_SWAP((s)->guid, d, 24, 8);\ 774 775 #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ 776 SQUASHFS_SWAP_START\ 777 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ 778 } 779 780 #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ 781 SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) 782 783 #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ 784 SQUASHFS_SWAP_START\ 785 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ 786 sizeof(struct squashfs_dev_inode_header_2)); \ 787 SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ 788 } 789 790 #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ 791 SQUASHFS_SWAP_START\ 792 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ 793 sizeof(struct squashfs_symlink_inode_header_2));\ 794 SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ 795 } 796 797 #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ 798 SQUASHFS_SWAP_START\ 799 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ 800 sizeof(struct squashfs_reg_inode_header_2));\ 801 SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ 802 SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ 803 SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ 804 SQUASHFS_SWAP((s)->offset, d, 128, 32);\ 805 SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ 806 } 807 808 #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ 809 SQUASHFS_SWAP_START\ 810 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ 811 sizeof(struct squashfs_dir_inode_header_2));\ 812 SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ 813 SQUASHFS_SWAP((s)->offset, d, 51, 13);\ 814 SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ 815 SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ 816 } 817 818 #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ 819 SQUASHFS_SWAP_START\ 820 SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ 821 sizeof(struct squashfs_ldir_inode_header_2));\ 822 SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ 823 SQUASHFS_SWAP((s)->offset, d, 59, 13);\ 824 SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ 825 SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ 826 SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ 827 } 828 829 #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ 830 SQUASHFS_SWAP_START\ 831 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ 832 SQUASHFS_SWAP((s)->index, d, 0, 27);\ 833 SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ 834 SQUASHFS_SWAP((s)->size, d, 56, 8);\ 835 } 836 #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ 837 SQUASHFS_SWAP_START\ 838 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ 839 SQUASHFS_SWAP((s)->count, d, 0, 8);\ 840 SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ 841 } 842 843 #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ 844 SQUASHFS_SWAP_START\ 845 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ 846 SQUASHFS_SWAP((s)->offset, d, 0, 13);\ 847 SQUASHFS_SWAP((s)->type, d, 13, 3);\ 848 SQUASHFS_SWAP((s)->size, d, 16, 8);\ 849 } 850 851 #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ 852 SQUASHFS_SWAP_START\ 853 SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ 854 SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ 855 SQUASHFS_SWAP((s)->size, d, 32, 32);\ 856 } 857 858 #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) 859 860 /* fragment and fragment table defines */ 861 #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) 862 863 #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ 864 SQUASHFS_METADATA_SIZE) 865 866 #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ 867 SQUASHFS_METADATA_SIZE) 868 869 #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ 870 SQUASHFS_METADATA_SIZE - 1) / \ 871 SQUASHFS_METADATA_SIZE) 872 873 #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ 874 sizeof(int)) 875 876 #endif 877 878 #ifdef __KERNEL__ 879 880 /* 881 * macros used to swap each structure entry, taking into account 882 * bitfields and different bitfield placing conventions on differing 883 * architectures 884 */ 885 886 #include <asm/byteorder.h> 887 888 #ifdef __BIG_ENDIAN 889 /* convert from little endian to big endian */ 890 #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ 891 tbits, b_pos) 892 #else 893 /* convert from big endian to little endian */ 894 #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ 895 tbits, 64 - tbits - b_pos) 896 #endif 897 898 #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ 899 b_pos = pos % 8;\ 900 val = 0;\ 901 s = (unsigned char *)p + (pos / 8);\ 902 d = ((unsigned char *) &val) + 7;\ 903 for(bits = 0; bits < (tbits + b_pos); bits += 8) \ 904 *d-- = *s++;\ 905 value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ 906 } 907 908 #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); 909 910 #endif 911 #endif -
include/linux/squashfs_fs_i.h
diff -Nru linux-2.6.19.ori2/include/linux/squashfs_fs_i.h linux-2.6.19.ori/include/linux/squashfs_fs_i.h
old new 1 #ifndef SQUASHFS_FS_I 2 #define SQUASHFS_FS_I 3 /* 4 * Squashfs 5 * 6 * Copyright (c) 2002, 2003, 2004, 2005, 2006 7 * Phillip Lougher <phillip@lougher.org.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_i.h 24 */ 25 26 struct squashfs_inode_info { 27 long long start_block; 28 unsigned int offset; 29 union { 30 struct { 31 long long fragment_start_block; 32 unsigned int fragment_size; 33 unsigned int fragment_offset; 34 long long block_list_start; 35 } s1; 36 struct { 37 long long directory_index_start; 38 unsigned int directory_index_offset; 39 unsigned int directory_index_count; 40 unsigned int parent_inode; 41 } s2; 42 } u; 43 struct inode vfs_inode; 44 }; 45 #endif -
include/linux/squashfs_fs_sb.h
diff -Nru linux-2.6.19.ori2/include/linux/squashfs_fs_sb.h linux-2.6.19.ori/include/linux/squashfs_fs_sb.h
old new 1 #ifndef SQUASHFS_FS_SB 2 #define SQUASHFS_FS_SB 3 /* 4 * Squashfs 5 * 6 * Copyright (c) 2002, 2003, 2004, 2005, 2006 7 * Phillip Lougher <phillip@lougher.org.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_sb.h 24 */ 25 26 #include <linux/squashfs_fs.h> 27 28 struct squashfs_cache { 29 long long block; 30 int length; 31 long long next_index; 32 char *data; 33 }; 34 35 struct squashfs_fragment_cache { 36 long long block; 37 int length; 38 unsigned int locked; 39 char *data; 40 }; 41 42 struct squashfs_sb_info { 43 struct squashfs_super_block sblk; 44 int devblksize; 45 int devblksize_log2; 46 int swap; 47 struct squashfs_cache *block_cache; 48 struct squashfs_fragment_cache *fragment; 49 int next_cache; 50 int next_fragment; 51 int next_meta_index; 52 unsigned int *uid; 53 unsigned int *guid; 54 long long *fragment_index; 55 unsigned int *fragment_index_2; 56 unsigned int read_size; 57 char *read_data; 58 char *read_page; 59 struct semaphore read_data_mutex; 60 struct semaphore read_page_mutex; 61 struct semaphore block_cache_mutex; 62 struct semaphore fragment_mutex; 63 struct semaphore meta_index_mutex; 64 wait_queue_head_t waitq; 65 wait_queue_head_t fragment_wait_queue; 66 struct meta_index *meta_index; 67 z_stream stream; 68 struct inode *(*iget)(struct super_block *s, squashfs_inode_t 69 inode); 70 long long (*read_blocklist)(struct inode *inode, int 71 index, int readahead_blks, char *block_list, 72 unsigned short **block_p, unsigned int *bsize); 73 int (*read_fragment_index_table)(struct super_block *s); 74 }; 75 #endif -
init/do_mounts_rd.c
diff -Nru linux-2.6.19.ori2/init/do_mounts_rd.c linux-2.6.19.ori/init/do_mounts_rd.c
old new 5 5 #include <linux/ext2_fs.h> 6 6 #include <linux/romfs_fs.h> 7 7 #include <linux/cramfs_fs.h> 8 #include <linux/squashfs_fs.h> 8 9 #include <linux/initrd.h> 9 10 #include <linux/string.h> 10 11 … … 39 40 * numbers could not be found. 40 41 * 41 42 * We currently check for the following magic numbers: 43 * squashfs 42 44 * minix 43 45 * ext2 44 46 * romfs … … 53 55 struct ext2_super_block *ext2sb; 54 56 struct romfs_super_block *romfsb; 55 57 struct cramfs_super *cramfsb; 58 struct squashfs_super_block *squashfsb; 56 59 int nblocks = -1; 57 60 unsigned char *buf; 58 61 … … 64 67 ext2sb = (struct ext2_super_block *) buf; 65 68 romfsb = (struct romfs_super_block *) buf; 66 69 cramfsb = (struct cramfs_super *) buf; 70 squashfsb = (struct squashfs_super_block *) buf; 67 71 memset(buf, 0xe5, size); 68 72 69 73 /* … … 101 105 goto done; 102 106 } 103 107 108 /* squashfs is at block zero too */ 109 if (squashfsb->s_magic == SQUASHFS_MAGIC) { 110 printk(KERN_NOTICE 111 "RAMDISK: squashfs filesystem found at block %d\n", 112 start_block); 113 if (squashfsb->s_major < 3) 114 nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; 115 else 116 nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; 117 goto done; 118 } 119 104 120 /* 105 121 * Read block 1 to test for minix and ext2 superblock 106 122 */
Note:
See TracBrowser
for help on using the repository browser.