allow coexistance of N build and AC build.
[tomato.git] / release / src-rt / linux / linux-2.6 / scripts / squashfs / read_fs.c
blob58eac0b5f7bfaf2b414f6629181541e02d820bc7
1 /*
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.
21 * read_fs.c
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);
27 #define TRUE 1
28 #define FALSE 0
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <zlib.h>
36 #include <sys/mman.h>
38 #ifndef linux
39 #define __BYTE_ORDER BYTE_ORDER
40 #define __BIG_ENDIAN BIG_ENDIAN
41 #define __LITTLE_ENDIAN LITTLE_ENDIAN
42 #else
43 #include <endian.h>
44 #endif
46 #include <squashfs_fs.h>
47 #include "read_fs.h"
48 #include "global.h"
50 #include <stdlib.h>
52 #ifdef SQUASHFS_TRACE
53 #define TRACE(s, args...) do { \
54 printf("mksquashfs: "s, ## args); \
55 } while(0)
56 #else
57 #define TRACE(s, args...)
58 #endif
60 #define ERROR(s, args...) do { \
61 fprintf(stderr, s, ## args); \
62 } while(0)
64 int swap;
66 int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk)
68 unsigned short c_byte;
69 int offset = 2;
71 if(swap) {
72 read_bytes(fd, start, 2, (char *) block);
73 ((unsigned char *) &c_byte)[1] = block[0];
74 ((unsigned char *) &c_byte)[0] = block[1];
75 } else
76 read_bytes(fd, start, 2, (char *)&c_byte);
78 if(SQUASHFS_CHECK_DATA(sBlk->flags))
79 offset = 3;
80 if(SQUASHFS_COMPRESSED(c_byte)) {
81 char buffer[SQUASHFS_METADATA_SIZE];
82 int res;
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");
93 else
94 ERROR("zlib::uncompress failed, unknown error %d\n", res);
95 return 0;
97 if(next)
98 *next = start + offset + c_byte;
99 return bytes;
100 } else {
101 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
102 read_bytes(fd, start + offset, c_byte, (char *) block);
103 if(next)
104 *next = start + offset + c_byte;
105 return 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);
122 while(start < end) {
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))
129 return FALSE;
130 TRACE("scan_inode_table: reading block 0x%llx\n", start);
131 if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) {
132 free(*inode_table);
133 return FALSE;
135 bytes += byte;
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;
148 if(swap) {
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));
152 } else
153 memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base));
154 if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) {
155 if(swap) {
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);
159 } else
160 memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir));
161 directory_start_block = dir_inode->dir.start_block;
162 } else {
163 if(swap) {
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);
167 } else
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 ++) {
173 if(swap) {
174 squashfs_reg_inode_header sinode;
175 memcpy(&sinode, cur_ptr, sizeof(inode));
176 SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode);
177 } else
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,
181 inode.inode_type);
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 >>
187 sBlk->block_log;
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");
196 goto failed;
199 cur_ptr += sizeof(inode);
200 if(swap) {
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);
204 } else
205 memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int));
207 *uncompressed_file += inode.file_size;
208 (*file_count) ++;
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);
215 break;
217 case SQUASHFS_LREG_TYPE: {
218 squashfs_lreg_inode_header inode;
219 int frag_bytes;
220 int blocks;
221 long long file_bytes = 0;
222 int i, start;
223 unsigned int *block_list;
225 if(swap) {
226 squashfs_lreg_inode_header sinodep;
227 memcpy(&sinodep, cur_ptr, sizeof(sinodep));
228 SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep);
229 } else
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 >>
238 sBlk->block_log;
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");
243 goto failed;
246 if(swap) {
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);
250 } else
251 memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int));
253 *uncompressed_file += inode.file_size;
254 (*file_count) ++;
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);
261 break;
263 case SQUASHFS_SYMLINK_TYPE: {
264 squashfs_symlink_inode_header inodep;
266 if(swap) {
267 squashfs_symlink_inode_header sinodep;
268 memcpy(&sinodep, cur_ptr, sizeof(sinodep));
269 SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep);
270 } else
271 memcpy(&inodep, cur_ptr, sizeof(inodep));
272 (*sym_count) ++;
273 cur_ptr += sizeof(inodep) + inodep.symlink_size;
274 break;
276 case SQUASHFS_DIR_TYPE: {
277 squashfs_dir_inode_header dir_inode;
279 if(swap) {
280 squashfs_dir_inode_header sinode;
281 memcpy(&sinode, cur_ptr, sizeof(dir_inode));
282 SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode);
283 } else
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;
287 (*dir_count) ++;
288 cur_ptr += sizeof(squashfs_dir_inode_header);
289 break;
291 case SQUASHFS_LDIR_TYPE: {
292 squashfs_ldir_inode_header dir_inode;
293 int i;
295 if(swap) {
296 squashfs_ldir_inode_header sinode;
297 memcpy(&sinode, cur_ptr, sizeof(dir_inode));
298 SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode);
299 } else
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;
303 (*dir_count) ++;
304 cur_ptr += sizeof(squashfs_ldir_inode_header);
305 for(i = 0; i < dir_inode.i_count; i++) {
306 squashfs_dir_index index;
307 if(swap) {
308 squashfs_dir_index sindex;
309 memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index));
310 SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
311 } else
312 memcpy(&index, cur_ptr, sizeof(squashfs_dir_index));
313 cur_ptr += sizeof(squashfs_dir_index) + index.size + 1;
315 break;
317 case SQUASHFS_BLKDEV_TYPE:
318 case SQUASHFS_CHRDEV_TYPE:
319 (*dev_count) ++;
320 cur_ptr += sizeof(squashfs_dev_inode_header);
321 break;
323 case SQUASHFS_FIFO_TYPE:
324 (*fifo_count) ++;
325 cur_ptr += sizeof(squashfs_ipc_inode_header);
326 break;
327 case SQUASHFS_SOCKET_TYPE:
328 (*sock_count) ++;
329 cur_ptr += sizeof(squashfs_ipc_inode_header);
330 break;
331 default:
332 ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type);
333 goto failed;
337 return files;
340 failed:
341 free(*inode_table);
342 return FALSE;
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 */
351 swap = 0;
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));
358 swap = 1;
359 } else {
360 ERROR("Can't find a SQUASHFS superblock on %s\n", source);
361 goto failed_mount;
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);
369 else
370 ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n",
371 source, sBlk->s_major, sBlk->s_minor);
372 goto failed_mount;
375 #if __BYTE_ORDER == __BIG_ENDIAN
376 *be = !swap;
377 #else
378 *be = swap;
379 #endif
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);
399 printf("\n");
401 return TRUE;
403 failed_mount:
404 return FALSE;
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;
418 size += offset;
419 if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL)
420 return 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);
426 return NULL;
428 bytes += byte;
431 if(!root_entries)
432 goto all_done;
434 bytes = offset;
435 while(bytes < size) {
436 if(swap) {
437 squashfs_dir_header sdirh;
438 memcpy(&sdirh, directory_table + bytes, sizeof(sdirh));
439 SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
440 } else
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);
447 while(dir_count--) {
448 if(swap) {
449 squashfs_dir_entry sdire;
450 memcpy(&sdire, directory_table + bytes, sizeof(sdire));
451 SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
452 } else
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;
464 all_done:
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)
477 return 1;
479 if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) {
480 ERROR("Failed to allocate fragment table\n");
481 return 0;
484 if(swap) {
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);
489 } else
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);
497 if(swap) {
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));
505 return 1;
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)
528 goto error;
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");
534 goto error;
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;
548 } else {
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");
559 goto error;
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");
565 goto error;
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");
571 goto error;
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");
577 goto error;
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");
583 goto error;
585 memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size);
587 if(!swap)
588 read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids);
589 else {
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);
596 if(!swap)
597 read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids);
598 else {
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;
607 free(inode_table);
608 free(directory_table);
609 return sBlk->inode_table_start;
612 error:
613 return 0;