2 * Read a squashfs filesystem. This is a highly compressed read only filesystem.
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006
5 * Phillip Lougher <phillip@lougher.org.uk>
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.
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.
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.
24 extern void read_bytes(int, long long, int, char *);
25 extern int add_file(long long, long long, unsigned int *, int, unsigned int, int, int);
30 #include <sys/types.h>
39 #define __BYTE_ORDER BYTE_ORDER
40 #define __BIG_ENDIAN BIG_ENDIAN
41 #define __LITTLE_ENDIAN LITTLE_ENDIAN
46 #include <squashfs_fs.h>
53 #define TRACE(s, args...) do { \
54 printf("mksquashfs: "s, ## args); \
57 #define TRACE(s, args...)
60 #define ERROR(s, args...) do { \
61 fprintf(stderr, s, ## args); \
66 int read_block(int fd
, long long start
, long long *next
, unsigned char *block
, squashfs_super_block
*sBlk
)
68 unsigned short c_byte
;
72 read_bytes(fd
, start
, 2, (char *) block
);
73 ((unsigned char *) &c_byte
)[1] = block
[0];
74 ((unsigned char *) &c_byte
)[0] = block
[1];
76 read_bytes(fd
, start
, 2, (char *)&c_byte
);
78 if(SQUASHFS_CHECK_DATA(sBlk
->flags
))
80 if(SQUASHFS_COMPRESSED(c_byte
)) {
81 char buffer
[SQUASHFS_METADATA_SIZE
];
83 unsigned long bytes
= SQUASHFS_METADATA_SIZE
;
85 c_byte
= SQUASHFS_COMPRESSED_SIZE(c_byte
);
86 read_bytes(fd
, start
+ offset
, c_byte
, buffer
);
88 if((res
= uncompress(block
, &bytes
, (const unsigned char *) buffer
, c_byte
)) != Z_OK
) {
89 if(res
== Z_MEM_ERROR
)
90 ERROR("zlib::uncompress failed, not enough memory\n");
91 else if(res
== Z_BUF_ERROR
)
92 ERROR("zlib::uncompress failed, not enough room in output buffer\n");
94 ERROR("zlib::uncompress failed, unknown error %d\n", res
);
98 *next
= start
+ offset
+ c_byte
;
101 c_byte
= SQUASHFS_COMPRESSED_SIZE(c_byte
);
102 read_bytes(fd
, start
+ offset
, c_byte
, (char *) block
);
104 *next
= start
+ offset
+ c_byte
;
110 int scan_inode_table(int fd
, long long start
, long long end
, long long root_inode_start
, int root_inode_offset
,
111 squashfs_super_block
*sBlk
,
112 squashfs_inode_header
*dir_inode
, unsigned char **inode_table
, unsigned int *root_inode_block
,
113 unsigned int *root_inode_size
, long long *uncompressed_file
, unsigned int *uncompressed_directory
,
114 int *file_count
, int *sym_count
, int *dev_count
, int *dir_count
, int *fifo_count
, int *sock_count
)
116 unsigned char *cur_ptr
;
117 int byte
, bytes
= 0, size
= 0, files
= 0;
118 squashfs_reg_inode_header inode
;
119 unsigned int directory_start_block
;
121 TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start
, end
, root_inode_start
);
123 if(start
== root_inode_start
) {
124 TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start
);
125 *root_inode_block
= bytes
;
127 if((size
- bytes
< SQUASHFS_METADATA_SIZE
) &&
128 ((*inode_table
= realloc(*inode_table
, size
+= SQUASHFS_METADATA_SIZE
)) == NULL
))
130 TRACE("scan_inode_table: reading block 0x%llx\n", start
);
131 if((byte
= read_block(fd
, start
, &start
, *inode_table
+ bytes
, sBlk
)) == 0) {
139 * Read last inode entry which is the root directory inode, and obtain the last
140 * directory start block index. This is used when calculating the total uncompressed
141 * directory size. The directory bytes in the last block will be counted as normal.
143 * The root inode is ignored in the inode scan. This ensures there is
144 * always enough bytes left to read a regular file inode entry
146 *root_inode_size
= bytes
- (*root_inode_block
+ root_inode_offset
);
147 bytes
= *root_inode_block
+ root_inode_offset
;
149 squashfs_base_inode_header sinode
;
150 memcpy(&sinode
, *inode_table
+ bytes
, sizeof(dir_inode
->base
));
151 SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode
->base
, &sinode
, sizeof(squashfs_base_inode_header
));
153 memcpy(&dir_inode
->base
, *inode_table
+ bytes
, sizeof(dir_inode
->base
));
154 if(dir_inode
->base
.inode_type
== SQUASHFS_DIR_TYPE
) {
156 squashfs_dir_inode_header sinode
;
157 memcpy(&sinode
, *inode_table
+ bytes
, sizeof(dir_inode
->dir
));
158 SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode
->dir
, &sinode
);
160 memcpy(&dir_inode
->dir
, *inode_table
+ bytes
, sizeof(dir_inode
->dir
));
161 directory_start_block
= dir_inode
->dir
.start_block
;
164 squashfs_ldir_inode_header sinode
;
165 memcpy(&sinode
, *inode_table
+ bytes
, sizeof(dir_inode
->ldir
));
166 SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode
->ldir
, &sinode
);
168 memcpy(&dir_inode
->ldir
, *inode_table
+ bytes
, sizeof(dir_inode
->ldir
));
169 directory_start_block
= dir_inode
->ldir
.start_block
;
172 for(cur_ptr
= *inode_table
; cur_ptr
< *inode_table
+ bytes
; files
++) {
174 squashfs_reg_inode_header sinode
;
175 memcpy(&sinode
, cur_ptr
, sizeof(inode
));
176 SQUASHFS_SWAP_REG_INODE_HEADER(&inode
, &sinode
);
178 memcpy(&inode
, cur_ptr
, sizeof(inode
));
180 TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr
- *inode_table
,
182 switch(inode
.inode_type
) {
183 case SQUASHFS_FILE_TYPE
: {
184 int frag_bytes
= inode
.fragment
== SQUASHFS_INVALID_FRAG
? 0 : inode
.file_size
% sBlk
->block_size
;
185 int blocks
= inode
.fragment
== SQUASHFS_INVALID_FRAG
? (inode
.file_size
186 + sBlk
->block_size
- 1) >> sBlk
->block_log
: inode
.file_size
>>
188 long long file_bytes
= 0;
189 int i
, start
= inode
.start_block
;
190 unsigned int *block_list
;
192 TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode
.file_size
, blocks
);
194 if((block_list
= malloc(blocks
* sizeof(unsigned int))) == NULL
) {
195 ERROR("Out of memory in block list malloc\n");
199 cur_ptr
+= sizeof(inode
);
201 unsigned int sblock_list
[blocks
];
202 memcpy(sblock_list
, cur_ptr
, blocks
* sizeof(unsigned int));
203 SQUASHFS_SWAP_INTS(block_list
, sblock_list
, blocks
);
205 memcpy(block_list
, cur_ptr
, blocks
* sizeof(unsigned int));
207 *uncompressed_file
+= inode
.file_size
;
210 for(i
= 0; i
< blocks
; i
++)
211 file_bytes
+= SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list
[i
]);
213 add_file(start
, file_bytes
, block_list
, blocks
, inode
.fragment
, inode
.offset
, frag_bytes
);
214 cur_ptr
+= blocks
* sizeof(unsigned int);
217 case SQUASHFS_LREG_TYPE
: {
218 squashfs_lreg_inode_header inode
;
221 long long file_bytes
= 0;
223 unsigned int *block_list
;
226 squashfs_lreg_inode_header sinodep
;
227 memcpy(&sinodep
, cur_ptr
, sizeof(sinodep
));
228 SQUASHFS_SWAP_LREG_INODE_HEADER(&inode
, &sinodep
);
230 memcpy(&inode
, cur_ptr
, sizeof(inode
));
232 TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode
.file_size
, blocks
);
234 cur_ptr
+= sizeof(inode
);
235 frag_bytes
= inode
.fragment
== SQUASHFS_INVALID_FRAG
? 0 : inode
.file_size
% sBlk
->block_size
;
236 blocks
= inode
.fragment
== SQUASHFS_INVALID_FRAG
? (inode
.file_size
237 + sBlk
->block_size
- 1) >> sBlk
->block_log
: inode
.file_size
>>
239 start
= inode
.start_block
;
241 if((block_list
= malloc(blocks
* sizeof(unsigned int))) == NULL
) {
242 ERROR("Out of memory in block list malloc\n");
247 unsigned int sblock_list
[blocks
];
248 memcpy(sblock_list
, cur_ptr
, blocks
* sizeof(unsigned int));
249 SQUASHFS_SWAP_INTS(block_list
, sblock_list
, blocks
);
251 memcpy(block_list
, cur_ptr
, blocks
* sizeof(unsigned int));
253 *uncompressed_file
+= inode
.file_size
;
256 for(i
= 0; i
< blocks
; i
++)
257 file_bytes
+= SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list
[i
]);
259 add_file(start
, file_bytes
, block_list
, blocks
, inode
.fragment
, inode
.offset
, frag_bytes
);
260 cur_ptr
+= blocks
* sizeof(unsigned int);
263 case SQUASHFS_SYMLINK_TYPE
: {
264 squashfs_symlink_inode_header inodep
;
267 squashfs_symlink_inode_header sinodep
;
268 memcpy(&sinodep
, cur_ptr
, sizeof(sinodep
));
269 SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep
, &sinodep
);
271 memcpy(&inodep
, cur_ptr
, sizeof(inodep
));
273 cur_ptr
+= sizeof(inodep
) + inodep
.symlink_size
;
276 case SQUASHFS_DIR_TYPE
: {
277 squashfs_dir_inode_header dir_inode
;
280 squashfs_dir_inode_header sinode
;
281 memcpy(&sinode
, cur_ptr
, sizeof(dir_inode
));
282 SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode
, &sinode
);
284 memcpy(&dir_inode
, cur_ptr
, sizeof(dir_inode
));
285 if(dir_inode
.start_block
< directory_start_block
)
286 *uncompressed_directory
+= dir_inode
.file_size
;
288 cur_ptr
+= sizeof(squashfs_dir_inode_header
);
291 case SQUASHFS_LDIR_TYPE
: {
292 squashfs_ldir_inode_header dir_inode
;
296 squashfs_ldir_inode_header sinode
;
297 memcpy(&sinode
, cur_ptr
, sizeof(dir_inode
));
298 SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode
, &sinode
);
300 memcpy(&dir_inode
, cur_ptr
, sizeof(dir_inode
));
301 if(dir_inode
.start_block
< directory_start_block
)
302 *uncompressed_directory
+= dir_inode
.file_size
;
304 cur_ptr
+= sizeof(squashfs_ldir_inode_header
);
305 for(i
= 0; i
< dir_inode
.i_count
; i
++) {
306 squashfs_dir_index index
;
308 squashfs_dir_index sindex
;
309 memcpy(&sindex
, cur_ptr
, sizeof(squashfs_dir_index
));
310 SQUASHFS_SWAP_DIR_INDEX(&index
, &sindex
);
312 memcpy(&index
, cur_ptr
, sizeof(squashfs_dir_index
));
313 cur_ptr
+= sizeof(squashfs_dir_index
) + index
.size
+ 1;
317 case SQUASHFS_BLKDEV_TYPE
:
318 case SQUASHFS_CHRDEV_TYPE
:
320 cur_ptr
+= sizeof(squashfs_dev_inode_header
);
323 case SQUASHFS_FIFO_TYPE
:
325 cur_ptr
+= sizeof(squashfs_ipc_inode_header
);
327 case SQUASHFS_SOCKET_TYPE
:
329 cur_ptr
+= sizeof(squashfs_ipc_inode_header
);
332 ERROR("Unknown inode type %d in scan_inode_table!\n", inode
.inode_type
);
346 int read_super(int fd
, squashfs_super_block
*sBlk
, int *be
, char *source
)
348 read_bytes(fd
, SQUASHFS_START
, sizeof(squashfs_super_block
), (char *) sBlk
);
350 /* Check it is a SQUASHFS superblock */
352 if(sBlk
->s_magic
!= SQUASHFS_MAGIC
) {
353 if(sBlk
->s_magic
== SQUASHFS_MAGIC_SWAP
) {
354 squashfs_super_block sblk
;
355 ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source
);
356 SQUASHFS_SWAP_SUPER_BLOCK(&sblk
, sBlk
);
357 memcpy(sBlk
, &sblk
, sizeof(squashfs_super_block
));
360 ERROR("Can't find a SQUASHFS superblock on %s\n", source
);
365 /* Check the MAJOR & MINOR versions */
366 if(sBlk
->s_major
!= SQUASHFS_MAJOR
|| sBlk
->s_minor
> SQUASHFS_MINOR
) {
367 if(sBlk
->s_major
< 3)
368 ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source
, sBlk
->s_major
, sBlk
->s_minor
, sBlk
->s_major
, sBlk
->s_minor
);
370 ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n",
371 source
, sBlk
->s_major
, sBlk
->s_minor
);
375 #if __BYTE_ORDER == __BIG_ENDIAN
381 printf("Found a valid SQUASHFS superblock on %s.\n", source
);
382 printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk
->flags
) ? "un" : "");
383 printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk
->flags
) ? "un" : "");
384 printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk
->flags
) ? "un" : "");
385 printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk
->flags
) ? "" : "not");
386 printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk
->flags
) ? "not" : "");
387 printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk
->flags
) ? "" : "not");
388 printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk
->flags
) ? "" : "not");
389 printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk
->bytes_used
/ 1024.0, sBlk
->bytes_used
/ (1024.0 * 1024.0));
390 printf("\tBlock size %d\n", sBlk
->block_size
);
391 printf("\tNumber of fragments %d\n", sBlk
->fragments
);
392 printf("\tNumber of inodes %d\n", sBlk
->inodes
);
393 printf("\tNumber of uids %d\n", sBlk
->no_uids
);
394 printf("\tNumber of gids %d\n", sBlk
->no_guids
);
395 TRACE("sBlk->inode_table_start %llx\n", sBlk
->inode_table_start
);
396 TRACE("sBlk->directory_table_start %llx\n", sBlk
->directory_table_start
);
397 TRACE("sBlk->uid_start %llx\n", sBlk
->uid_start
);
398 TRACE("sBlk->fragment_table_start %llx\n", sBlk
->fragment_table_start
);
408 unsigned char *squashfs_readdir(int fd
, int root_entries
, unsigned int directory_start_block
, int offset
, int size
,
409 unsigned int *last_directory_block
, squashfs_super_block
*sBlk
, void (push_directory_entry
)(char *, squashfs_inode
, int, int))
411 squashfs_dir_header dirh
;
412 char buffer
[sizeof(squashfs_dir_entry
) + SQUASHFS_NAME_LEN
+ 1];
413 squashfs_dir_entry
*dire
= (squashfs_dir_entry
*) buffer
;
414 unsigned char *directory_table
= NULL
;
415 int byte
, bytes
= 0, dir_count
;
416 long long start
= sBlk
->directory_table_start
+ directory_start_block
, last_start_block
;
419 if((directory_table
= malloc((size
+ SQUASHFS_METADATA_SIZE
* 2 - 1) & ~(SQUASHFS_METADATA_SIZE
- 1))) == NULL
)
421 while(bytes
< size
) {
422 TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start
, bytes
);
423 last_start_block
= start
;
424 if((byte
= read_block(fd
, start
, &start
, directory_table
+ bytes
, sBlk
)) == 0) {
425 free(directory_table
);
435 while(bytes
< size
) {
437 squashfs_dir_header sdirh
;
438 memcpy(&sdirh
, directory_table
+ bytes
, sizeof(sdirh
));
439 SQUASHFS_SWAP_DIR_HEADER(&dirh
, &sdirh
);
441 memcpy(&dirh
, directory_table
+ bytes
, sizeof(dirh
));
443 dir_count
= dirh
.count
+ 1;
444 TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes
, dir_count
);
445 bytes
+= sizeof(dirh
);
449 squashfs_dir_entry sdire
;
450 memcpy(&sdire
, directory_table
+ bytes
, sizeof(sdire
));
451 SQUASHFS_SWAP_DIR_ENTRY(dire
, &sdire
);
453 memcpy(dire
, directory_table
+ bytes
, sizeof(dire
));
454 bytes
+= sizeof(*dire
);
456 memcpy(dire
->name
, directory_table
+ bytes
, dire
->size
+ 1);
457 dire
->name
[dire
->size
+ 1] = '\0';
458 TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire
->name
, dirh
.start_block
, dire
->offset
, dire
->type
);
459 push_directory_entry(dire
->name
, SQUASHFS_MKINODE(dirh
.start_block
, dire
->offset
), dirh
.inode_number
+ dire
->inode_number
, dire
->type
);
460 bytes
+= dire
->size
+ 1;
465 *last_directory_block
= (unsigned int) last_start_block
- sBlk
->directory_table_start
;
466 return directory_table
;
470 int read_fragment_table(int fd
, squashfs_super_block
*sBlk
, squashfs_fragment_entry
**fragment_table
)
472 int i
, indexes
= SQUASHFS_FRAGMENT_INDEXES(sBlk
->fragments
);
473 squashfs_fragment_index fragment_table_index
[indexes
];
475 TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk
->fragments
, indexes
, sBlk
->fragment_table_start
);
476 if(sBlk
->fragments
== 0)
479 if((*fragment_table
= (squashfs_fragment_entry
*) malloc(sBlk
->fragments
* sizeof(squashfs_fragment_entry
))) == NULL
) {
480 ERROR("Failed to allocate fragment table\n");
485 squashfs_fragment_index sfragment_table_index
[indexes
];
487 read_bytes(fd
, sBlk
->fragment_table_start
, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk
->fragments
), (char *) sfragment_table_index
);
488 SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index
, sfragment_table_index
, indexes
);
490 read_bytes(fd
, sBlk
->fragment_table_start
, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk
->fragments
), (char *) fragment_table_index
);
492 for(i
= 0; i
< indexes
; i
++) {
493 int length
= read_block(fd
, fragment_table_index
[i
], NULL
, ((unsigned char *) *fragment_table
) + (i
* SQUASHFS_METADATA_SIZE
), sBlk
);
494 TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i
, fragment_table_index
[i
], length
);
498 squashfs_fragment_entry sfragment
;
499 for(i
= 0; i
< sBlk
->fragments
; i
++) {
500 SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment
), (&(*fragment_table
)[i
]));
501 memcpy((char *) &(*fragment_table
)[i
], (char *) &sfragment
, sizeof(squashfs_fragment_entry
));
509 long long read_filesystem(char *root_name
, int fd
, squashfs_super_block
*sBlk
, char **cinode_table
,
510 char **data_cache
, char **cdirectory_table
, char **directory_data_cache
,
511 unsigned int *last_directory_block
, unsigned int *inode_dir_offset
, unsigned int *inode_dir_file_size
,
512 unsigned int *root_inode_size
, unsigned int *inode_dir_start_block
, int *file_count
, int *sym_count
,
513 int *dev_count
, int *dir_count
, int *fifo_count
, int *sock_count
, squashfs_uid
*uids
,
514 unsigned short *uid_count
, squashfs_uid
*guids
, unsigned short *guid_count
,
515 long long *uncompressed_file
, unsigned int *uncompressed_inode
, unsigned int *uncompressed_directory
,
516 unsigned int *inode_dir_inode_number
, unsigned int *inode_dir_parent_inode
,
517 void (push_directory_entry
)(char *, squashfs_inode
, int, int), squashfs_fragment_entry
**fragment_table
)
519 unsigned char *inode_table
= NULL
, *directory_table
;
520 long long start
= sBlk
->inode_table_start
, end
= sBlk
->directory_table_start
, root_inode_start
= start
+
521 SQUASHFS_INODE_BLK(sBlk
->root_inode
);
522 unsigned int root_inode_offset
= SQUASHFS_INODE_OFFSET(sBlk
->root_inode
), root_inode_block
, files
;
523 squashfs_inode_header inode
;
525 printf("Scanning existing filesystem...\n");
527 if(read_fragment_table(fd
, sBlk
, fragment_table
) == 0)
530 if((files
= scan_inode_table(fd
, start
, end
, root_inode_start
, root_inode_offset
, sBlk
, &inode
, &inode_table
,
531 &root_inode_block
, root_inode_size
, uncompressed_file
, uncompressed_directory
, file_count
, sym_count
,
532 dev_count
, dir_count
, fifo_count
, sock_count
)) == 0) {
533 ERROR("read_filesystem: inode table read failed\n");
537 *uncompressed_inode
= root_inode_block
;
539 printf("Read existing filesystem, %d inodes scanned\n", files
);
541 if(inode
.base
.inode_type
== SQUASHFS_DIR_TYPE
|| inode
.base
.inode_type
== SQUASHFS_LDIR_TYPE
) {
542 if(inode
.base
.inode_type
== SQUASHFS_DIR_TYPE
) {
543 *inode_dir_start_block
= inode
.dir
.start_block
;
544 *inode_dir_offset
= inode
.dir
.offset
;
545 *inode_dir_file_size
= inode
.dir
.file_size
- 3;
546 *inode_dir_inode_number
= inode
.dir
.inode_number
;
547 *inode_dir_parent_inode
= inode
.dir
.parent_inode
;
549 *inode_dir_start_block
= inode
.ldir
.start_block
;
550 *inode_dir_offset
= inode
.ldir
.offset
;
551 *inode_dir_file_size
= inode
.ldir
.file_size
- 3;
552 *inode_dir_inode_number
= inode
.ldir
.inode_number
;
553 *inode_dir_parent_inode
= inode
.ldir
.parent_inode
;
556 if((directory_table
= squashfs_readdir(fd
, !root_name
, *inode_dir_start_block
, *inode_dir_offset
,
557 *inode_dir_file_size
, last_directory_block
, sBlk
, push_directory_entry
)) == NULL
) {
558 ERROR("read_filesystem: Could not read root directory\n");
562 root_inode_start
-= start
;
563 if((*cinode_table
= (char *) malloc(root_inode_start
)) == NULL
) {
564 ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n");
567 read_bytes(fd
, start
, root_inode_start
, *cinode_table
);
569 if((*cdirectory_table
= (char *) malloc(*last_directory_block
)) == NULL
) {
570 ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n");
573 read_bytes(fd
, sBlk
->directory_table_start
, *last_directory_block
, *cdirectory_table
);
575 if((*data_cache
= (char *) malloc(root_inode_offset
+ *root_inode_size
)) == NULL
) {
576 ERROR("read_filesystem: failed to alloc inode cache\n");
579 memcpy(*data_cache
, inode_table
+ root_inode_block
, root_inode_offset
+ *root_inode_size
);
581 if((*directory_data_cache
= (char *) malloc(*inode_dir_offset
+ *inode_dir_file_size
)) == NULL
) {
582 ERROR("read_filesystem: failed to alloc directory cache\n");
585 memcpy(*directory_data_cache
, directory_table
, *inode_dir_offset
+ *inode_dir_file_size
);
588 read_bytes(fd
, sBlk
->uid_start
, sBlk
->no_uids
* sizeof(squashfs_uid
), (char *) uids
);
590 squashfs_uid uids_copy
[sBlk
->no_uids
];
592 read_bytes(fd
, sBlk
->uid_start
, sBlk
->no_uids
* sizeof(squashfs_uid
), (char *) uids_copy
);
593 SQUASHFS_SWAP_DATA(uids
, uids_copy
, sBlk
->no_uids
, sizeof(squashfs_uid
) * 8);
597 read_bytes(fd
, sBlk
->guid_start
, sBlk
->no_guids
* sizeof(squashfs_uid
), (char *) guids
);
599 squashfs_uid guids_copy
[sBlk
->no_guids
];
601 read_bytes(fd
, sBlk
->guid_start
, sBlk
->no_guids
* sizeof(squashfs_uid
), (char *) guids_copy
);
602 SQUASHFS_SWAP_DATA(guids
, guids_copy
, sBlk
->no_guids
, sizeof(squashfs_uid
) * 8);
604 *uid_count
= sBlk
->no_uids
;
605 *guid_count
= sBlk
->no_guids
;
608 free(directory_table
);
609 return sBlk
->inode_table_start
;