read_fs.c revision ce2fef5e9d6e31648e93bda430fee37f0929c583
11f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher/*
21ebb6e9932d448097d769f1366d8adaae797ea64plougher * Read a squashfs filesystem.  This is a highly compressed read only
31ebb6e9932d448097d769f1366d8adaae797ea64plougher * filesystem.
41f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
5096135f7430824033f597e47906a24d087f47a34Phillip Lougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
6b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher * 2012, 2013
783d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher * Phillip Lougher <phillip@squashfs.org.uk>
81f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
91f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * This program is free software; you can redistribute it and/or
101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * modify it under the terms of the GNU General Public License
111f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * as published by the Free Software Foundation; either version 2,
121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * or (at your option) any later version.
131f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
141f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * This program is distributed in the hope that it will be useful,
151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of
161f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * GNU General Public License for more details.
181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * You should have received a copy of the GNU General Public License
201f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * along with this program; if not, write to the Free Software
211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher * read_fs.c
241f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher */
251f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
261f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#define TRUE 1
271f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#define FALSE 0
281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <stdio.h>
291f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <sys/types.h>
301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <sys/stat.h>
311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <fcntl.h>
321f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <errno.h>
331f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <string.h>
341f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <sys/mman.h>
35125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher#include <limits.h>
36ce2fef5e9d6e31648e93bda430fee37f0929c583Phillip Lougher#include <dirent.h>
378cb05cde913bb04297020629566540981a649273plougher
3887c0c4afbf3b8ecc814f6bac4d90b70d1e109f44plougher#ifndef linux
398cb05cde913bb04297020629566540981a649273plougher#define __BYTE_ORDER BYTE_ORDER
408cb05cde913bb04297020629566540981a649273plougher#define __BIG_ENDIAN BIG_ENDIAN
418cb05cde913bb04297020629566540981a649273plougher#define __LITTLE_ENDIAN LITTLE_ENDIAN
428cb05cde913bb04297020629566540981a649273plougher#else
431f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <endian.h>
448cb05cde913bb04297020629566540981a649273plougher#endif
451f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
461f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <stdlib.h>
471f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
48860c1f3d8aa4ba40d587382a91821bea03b023c5plougher#include "squashfs_fs.h"
49860c1f3d8aa4ba40d587382a91821bea03b023c5plougher#include "squashfs_swap.h"
50860c1f3d8aa4ba40d587382a91821bea03b023c5plougher#include "compressor.h"
51860c1f3d8aa4ba40d587382a91821bea03b023c5plougher#include "xattr.h"
522477d0defc9d6dade582bb36596eed2e3cfddf8cPhillip Lougher#include "error.h"
53ce2fef5e9d6e31648e93bda430fee37f0929c583Phillip Lougher#include "mksquashfs.h"
54374444c9b3c6331d781625bec0a7550e05d01ed6plougher
5534c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougherstatic struct compressor *comp;
5634c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher
57b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougherint read_block(int fd, long long start, long long *next, int expected,
58b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher								void *block)
591f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
601f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned short c_byte;
61b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	int res, compressed;
62b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	int outlen = expected ? expected : SQUASHFS_METADATA_SIZE;
631f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
64b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/* Read block size */
653306cb2b54a60a32664617118336ac141e1471b6plougher	res = read_fs_bytes(fd, start, 2, &c_byte);
661d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0)
671d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
681d065e9f3c6d22a629134837a55538fb8619cfb4plougher
6961343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
70b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	compressed = SQUASHFS_COMPRESSED(c_byte);
71b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
721f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
73b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/*
74b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * The block size should not be larger than
75b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * the uncompressed size (or max uncompressed size if
76b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * expected is 0)
77b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 */
78b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if (c_byte > outlen)
79b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return 0;
80b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
81b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(compressed) {
82b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		char buffer[c_byte];
83b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		int error;
841f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
85540c7abc405a7a26373d5299e77122eae1365c56plougher		res = read_fs_bytes(fd, start + 2, c_byte, buffer);
861d065e9f3c6d22a629134837a55538fb8619cfb4plougher		if(res == 0)
871d065e9f3c6d22a629134837a55538fb8619cfb4plougher			return 0;
881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
89b48442b2e37b3cb7efbffb032968f115eec7963cplougher		res = compressor_uncompress(comp, block, buffer, c_byte,
90b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher			outlen, &error);
919f1e0e214eaff51604105b88153f2d77bc398158plougher		if(res == -1) {
929f1e0e214eaff51604105b88153f2d77bc398158plougher			ERROR("%s uncompress failed with error code %d\n",
939f1e0e214eaff51604105b88153f2d77bc398158plougher				comp->name, error);
941f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			return 0;
951f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	} else {
97540c7abc405a7a26373d5299e77122eae1365c56plougher		res = read_fs_bytes(fd, start + 2, c_byte, block);
981d065e9f3c6d22a629134837a55538fb8619cfb4plougher		if(res == 0)
991d065e9f3c6d22a629134837a55538fb8619cfb4plougher			return 0;
100b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		res = c_byte;
1011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
102b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
103b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(next)
104b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		*next = start + 2 + c_byte;
105b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
106b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/*
107b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * if expected, then check the (uncompressed) return data
108b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * is of the expected size
109b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 */
110b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(expected && expected != res)
111b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return 0;
112b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	else
113b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return res;
1147e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher}
115b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
116b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
1177e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher#define NO_BYTES(SIZE) \
1187e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	(bytes - (cur_ptr - *inode_table) < (SIZE))
1191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1207e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher#define NO_INODE_BYTES(INODE) NO_BYTES(sizeof(struct INODE))
1211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1221b899fc316f7eba7a31da12dc0c9b69ada441059plougherint scan_inode_table(int fd, long long start, long long end,
1231b899fc316f7eba7a31da12dc0c9b69ada441059plougher	long long root_inode_start, int root_inode_offset,
124e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	struct squashfs_super_block *sBlk, union squashfs_inode_header
125e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	*dir_inode, unsigned char **inode_table, unsigned int *root_inode_block,
1261b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *root_inode_size, long long *uncompressed_file,
1271b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *uncompressed_directory, int *file_count, int *sym_count,
1281b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int *dev_count, int *dir_count, int *fifo_count, int *sock_count,
1291b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *id_table)
1301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
1311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned char *cur_ptr;
1327e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	int byte, files = 0;
1337e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	unsigned int directory_start_block, bytes = 0, size = 0;
1347e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	struct squashfs_base_inode_header base;
1351f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
136e69aac119c4660c567d5159729b9875c3330e4bbplougher	TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start "
137e69aac119c4660c567d5159729b9875c3330e4bbplougher		"0x%llx\n", start, end, root_inode_start);
138e69aac119c4660c567d5159729b9875c3330e4bbplougher
139125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	*root_inode_block = UINT_MAX;
1401f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	while(start < end) {
1411f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		if(start == root_inode_start) {
142e69aac119c4660c567d5159729b9875c3330e4bbplougher			TRACE("scan_inode_table: read compressed block 0x%llx "
143e69aac119c4660c567d5159729b9875c3330e4bbplougher				"containing root inode\n", start);
1441f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*root_inode_block = bytes;
1451f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
146e69aac119c4660c567d5159729b9875c3330e4bbplougher		if(size - bytes < SQUASHFS_METADATA_SIZE) {
147e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_table = realloc(*inode_table, size
148e69aac119c4660c567d5159729b9875c3330e4bbplougher				+= SQUASHFS_METADATA_SIZE);
149e69aac119c4660c567d5159729b9875c3330e4bbplougher			if(*inode_table == NULL)
1509facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
151e69aac119c4660c567d5159729b9875c3330e4bbplougher		}
1524c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher		TRACE("scan_inode_table: reading block 0x%llx\n", start);
153b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		byte = read_block(fd, start, &start, 0, *inode_table + bytes);
1547e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(byte == 0)
15545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
1562b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher
1574c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher		bytes += byte;
1582b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher
1592b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		/* If this is not the last metadata block in the inode table
1602b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * then it should be SQUASHFS_METADATA_SIZE in size.
1612b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * Note, we can't use expected in read_block() above for this
1622b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * because we don't know if this is the last block until
1632b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * after reading.
1642b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 */
1657e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(start != end && byte != SQUASHFS_METADATA_SIZE)
16645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
1671f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
1681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1691f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	/*
170125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * We expect to have found the metadata block containing the
171125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * root inode in the above inode_table metadata block scan.  If it
172125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * hasn't been found then the filesystem is corrupted
173125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 */
1747e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if(*root_inode_block == UINT_MAX)
17545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
1767e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
1777e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	/*
1787e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * The number of bytes available after the root inode medata block
1797e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * should be at least the root inode offset + the size of a
1807e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * regular directory inode, if not the filesystem is corrupted
1817e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *
1827e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	+-----------------------+-----------------------+
1837e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	| 			|        directory	|
1847e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	|			|          inode	|
1857e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	+-----------------------+-----------------------+
1867e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	^			^			^
1877e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	*root_inode_block	root_inode_offset	bytes
1887e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 */
1897e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if((bytes - *root_inode_block) < (root_inode_offset +
1907e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			sizeof(struct squashfs_dir_inode_header)))
19145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
192125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher
193125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	/*
194e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * Read last inode entry which is the root directory inode, and obtain
195e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * the last directory start block index.  This is used when calculating
196e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * the total uncompressed directory size.  The directory bytes in the
197e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * last * block will be counted as normal.
1981f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	 *
1997e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * Note, the previous check ensures the following calculation won't
2007e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * underflow, and we won't access beyond the buffer
2011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	 */
2021f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	*root_inode_size = bytes - (*root_inode_block + root_inode_offset);
2031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	bytes = *root_inode_block + root_inode_offset;
204690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher	SQUASHFS_SWAP_DIR_INODE_HEADER(*inode_table + bytes, &dir_inode->dir);
2057e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
2067e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE)
2071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		directory_start_block = dir_inode->dir.start_block;
2087e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	else if(dir_inode->base.inode_type == SQUASHFS_LDIR_TYPE) {
2097e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(*root_inode_size < sizeof(struct squashfs_ldir_inode_header))
2107e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			/* corrupted filesystem */
21145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
212690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_LDIR_INODE_HEADER(*inode_table + bytes,
213690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			&dir_inode->ldir);
2141f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		directory_start_block = dir_inode->ldir.start_block;
2157e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	} else
2167e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		/* bad type, corrupted filesystem */
21745f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
2187e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
2191b899fc316f7eba7a31da12dc0c9b69ada441059plougher	get_uid(id_table[dir_inode->base.uid]);
2201b899fc316f7eba7a31da12dc0c9b69ada441059plougher	get_guid(id_table[dir_inode->base.guid]);
2211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
2221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) {
2237e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(NO_INODE_BYTES(squashfs_base_inode_header))
2247e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			/* corrupted filesystem */
22545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
2267e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
227690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_BASE_INODE_HEADER(cur_ptr, &base);
2281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
229e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("scan_inode_table: processing inode @ byte position "
230363ddaa1fcfd7e2bb186cb78990c43e491ea981dplougher			"0x%x, type 0x%x\n",
231363ddaa1fcfd7e2bb186cb78990c43e491ea981dplougher			(unsigned int) (cur_ptr - *inode_table),
2327e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			base.inode_type);
2331b899fc316f7eba7a31da12dc0c9b69ada441059plougher
2347e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		get_uid(id_table[base.uid]);
2357e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		get_guid(id_table[base.guid]);
2361b899fc316f7eba7a31da12dc0c9b69ada441059plougher
2377e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		switch(base.inode_type) {
238e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_FILE_TYPE: {
239e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_reg_inode_header inode;
240e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int frag_bytes, blocks, i;
241e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			long long start, file_bytes = 0;
242e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			unsigned int *block_list;
243e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
244e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_reg_inode_header))
245e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
24645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
2477e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
248690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_REG_INODE_HEADER(cur_ptr, &inode);
2497e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
250e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ?
251e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				0 : inode.file_size % sBlk->block_size;
252e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			blocks = inode.fragment == SQUASHFS_INVALID_FRAG ?
253e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				(inode.file_size + sBlk->block_size - 1) >>
254e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log : inode.file_size >>
255e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log;
256e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			start = inode.start_block;
2577e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
258e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			TRACE("scan_inode_table: regular file, file_size %d, "
259e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				"blocks %d\n", inode.file_size, blocks);
2601f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
261e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_BYTES(blocks * sizeof(unsigned int)))
262e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
26345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
2641f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
265e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			block_list = malloc(blocks * sizeof(unsigned int));
2669facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			if(block_list == NULL)
2679facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
2687e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
269e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(inode);
270690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);
2717e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
272e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			*uncompressed_file += inode.file_size;
273e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*file_count) ++;
274058eae41952c33345bd0ef290aea8eef37f3ca92plougher
275e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < blocks; i++)
276e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				file_bytes +=
277e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					SQUASHFS_COMPRESSED_SIZE_BLOCK
278e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher								(block_list[i]);
279058eae41952c33345bd0ef290aea8eef37f3ca92plougher
280e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			add_file(start, inode.file_size, file_bytes,
281e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				block_list, blocks, inode.fragment,
282e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.offset, frag_bytes);
283e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
284e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += blocks * sizeof(unsigned int);
285e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
286e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
287e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LREG_TYPE: {
288e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_lreg_inode_header inode;
289e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int frag_bytes, blocks, i;
290e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			long long start, file_bytes = 0;
291e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			unsigned int *block_list;
292e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
293e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lreg_inode_header))
294e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
29545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
296f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher
297690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_LREG_INODE_HEADER(cur_ptr, &inode);
2987e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
299e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ?
300e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				0 : inode.file_size % sBlk->block_size;
301e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			blocks = inode.fragment == SQUASHFS_INVALID_FRAG ?
302e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				(inode.file_size + sBlk->block_size - 1) >>
303e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log : inode.file_size >>
304e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log;
305e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			start = inode.start_block;
306570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
307e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			TRACE("scan_inode_table: extended regular "
308e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				"file, file_size %lld, blocks %d\n",
309e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.file_size, blocks);
310570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
311e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_BYTES(blocks * sizeof(unsigned int)))
312e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
31345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
3147e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
315e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			block_list = malloc(blocks * sizeof(unsigned int));
3169facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			if(block_list == NULL)
3179facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
3181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
319e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(inode);
320690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);
3211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
322e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			*uncompressed_file += inode.file_size;
323e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*file_count) ++;
3247e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
325e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < blocks; i++)
326e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				file_bytes +=
327e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					SQUASHFS_COMPRESSED_SIZE_BLOCK
328e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher								(block_list[i]);
3297e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
330e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			add_file(start, inode.file_size, file_bytes,
331e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				block_list, blocks, inode.fragment,
332e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.offset, frag_bytes);
3337e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
334e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += blocks * sizeof(unsigned int);
335e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
336e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
337e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_SYMLINK_TYPE:
338e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LSYMLINK_TYPE: {
339e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_symlink_inode_header inode;
34061343797593e92ad2cf75b221398c138e1fee058plougher
341e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_symlink_inode_header))
342e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
34345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
3447e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
345690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_SYMLINK_INODE_HEADER(cur_ptr, &inode);
3467e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
347e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sym_count) ++;
3487e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
349e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if (inode.inode_type == SQUASHFS_LSYMLINK_TYPE) {
350e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(inode.symlink_size +
351e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher							sizeof(unsigned int)))
3527e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
35345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
354e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(inode) + inode.symlink_size +
355e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher							sizeof(unsigned int);
356e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			} else {
357e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(inode.symlink_size))
3587e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
35945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
360e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(inode) + inode.symlink_size;
361e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			}
362e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
363e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
364e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_DIR_TYPE: {
365e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_dir_inode_header dir_inode;
3667e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
367e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_dir_inode_header))
368e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
36945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
370e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
371690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_DIR_INODE_HEADER(cur_ptr, &dir_inode);
372e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
373e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(dir_inode.start_block < directory_start_block)
374e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				*uncompressed_directory += dir_inode.file_size;
375e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
376e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dir_count) ++;
377e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_dir_inode_header);
378e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
379e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
380e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LDIR_TYPE: {
381e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_ldir_inode_header dir_inode;
382e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int i;
3837e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
384e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ldir_inode_header))
385e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
38645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
387e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
388690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_LDIR_INODE_HEADER(cur_ptr, &dir_inode);
389e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
390e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(dir_inode.start_block < directory_start_block)
391e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				*uncompressed_directory += dir_inode.file_size;
392e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
393e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dir_count) ++;
394e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ldir_inode_header);
395e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
396e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < dir_inode.i_count; i++) {
397e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				struct squashfs_dir_index index;
398e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
399e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(sizeof(index)))
4007e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
40145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
402e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
403690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher				SQUASHFS_SWAP_DIR_INDEX(cur_ptr, &index);
4047e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
405e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(index.size + 1))
4067e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
40745f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
4087e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
409e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(index) + index.size + 1;
410e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			}
411e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
412e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
413e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_BLKDEV_TYPE:
414e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_CHRDEV_TYPE:
415e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_dev_inode_header))
416e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
41745f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
418e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
419e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dev_count) ++;
420e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_dev_inode_header);
421e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
422e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_LBLKDEV_TYPE:
423e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_LCHRDEV_TYPE:
424e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ldev_inode_header))
425e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
42645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
427e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
428e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dev_count) ++;
429e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ldev_inode_header);
430e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
431e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_FIFO_TYPE:
432e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ipc_inode_header))
433e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
43445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
435e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
436e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*fifo_count) ++;
437e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ipc_inode_header);
438e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
439e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LFIFO_TYPE:
440e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lipc_inode_header))
441e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
44245f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
443e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
444e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*fifo_count) ++;
445e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_lipc_inode_header);
446e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
447e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_SOCKET_TYPE:
448e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ipc_inode_header))
449e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
45045f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
451e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
452e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sock_count) ++;
453e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ipc_inode_header);
454e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
455e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LSOCKET_TYPE:
456e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lipc_inode_header))
457e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
45845f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
459e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
460e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sock_count) ++;
461e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_lipc_inode_header);
462e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
463e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	default:
464e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			ERROR("Unknown inode type %d in scan_inode_table!\n",
465e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					base.inode_type);
46645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
4671f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
4681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
4691f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
4701a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	printf("Read existing filesystem, %d inodes scanned\n", files);
4711a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	return TRUE;
472058eae41952c33345bd0ef290aea8eef37f3ca92plougher
47345f78347049325b32c0ab96e6858f3f2bb993532Phillip Loughercorrupted:
47445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher	ERROR("scan_inode_table: filesystem corruption detected in "
47545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		"scanning metadata\n");
476058eae41952c33345bd0ef290aea8eef37f3ca92plougher	free(*inode_table);
477058eae41952c33345bd0ef290aea8eef37f3ca92plougher	return FALSE;
4781f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
4791f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
4801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
48164e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherstruct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source)
4821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
483317959322c665d211788f07227abcba61984ec88plougher	int res, bytes = 0;
484f6310758b1c84e5f7223425bfaaee97eb962a506plougher	char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));
4851d065e9f3c6d22a629134837a55538fb8619cfb4plougher
48664e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher	res = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block),
4873306cb2b54a60a32664617118336ac141e1471b6plougher		sBlk);
48863ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher	if(res == 0) {
48963ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher		ERROR("Can't find a SQUASHFS superblock on %s\n",
49063ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher				source);
49163ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher		ERROR("Wrong filesystem or filesystem is corrupted!\n");
4921d065e9f3c6d22a629134837a55538fb8619cfb4plougher		goto failed_mount;
49363ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher	}
4941d065e9f3c6d22a629134837a55538fb8619cfb4plougher
49561343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_SUPER_BLOCK(sBlk);
4961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
4971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->s_magic != SQUASHFS_MAGIC) {
4982702e98268c66397751f9ed996a6460f216dba34plougher		if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP)
4992702e98268c66397751f9ed996a6460f216dba34plougher			ERROR("Pre 4.0 big-endian filesystem on %s, appending"
5002702e98268c66397751f9ed996a6460f216dba34plougher				" to this is unsupported\n", source);
5010372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher		else {
502e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			ERROR("Can't find a SQUASHFS superblock on %s\n",
503e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				source);
5040372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher			ERROR("Wrong filesystem or filesystem is corrupted!\n");
5050372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher		}
5062702e98268c66397751f9ed996a6460f216dba34plougher		goto failed_mount;
5071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
5081f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
5091f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	/* Check the MAJOR & MINOR versions */
5101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
511f83fbe8fc5e688b288f34865cc885a5711118221plougher		if(sBlk->s_major < 4)
512e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem."
513e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"  Appending\nto SQUASHFS %d.%d filesystems is "
514e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"not supported.  Please convert it to a "
515e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"SQUASHFS 4 filesystem\n", source,
516e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				sBlk->s_major,
517e69aac119c4660c567d5159729b9875c3330e4bbplougher				sBlk->s_minor, sBlk->s_major, sBlk->s_minor);
5181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		else
519e69aac119c4660c567d5159729b9875c3330e4bbplougher			ERROR("Filesystem on %s is %d.%d, which is a later "
520e69aac119c4660c567d5159729b9875c3330e4bbplougher				"filesystem version than I support\n",
521df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher				source, sBlk->s_major, sBlk->s_minor);
5221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto failed_mount;
5231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
5241f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
52534c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	/* Check the compression type */
52634c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	comp = lookup_compressor_id(sBlk->compression);
52734c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	if(!comp->supported) {
52848c97065cf29dff24d01d94b39f4fdc6cef815f2Phillip Lougher		ERROR("Filesystem on %s uses %s compression, this is "
52934c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher			"unsupported by this version\n", source, comp->name);
530f09d9a6589de25eb4b9c9891277a717c1053a400plougher		ERROR("Compressors available:\n");
531764dab5cd71bda25bc755de08908dbbd58c1a450plougher		display_compressors("", "");
53234c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher		goto failed_mount;
53334c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	}
53434c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher
5355924372bba7ac923cca996e74716128a98f668afplougher	/*
5365924372bba7ac923cca996e74716128a98f668afplougher	 * Read extended superblock information from disk.
5375924372bba7ac923cca996e74716128a98f668afplougher	 *
5385924372bba7ac923cca996e74716128a98f668afplougher	 * Read compressor specific options from disk if present, and pass
5395924372bba7ac923cca996e74716128a98f668afplougher	 * to compressor to set compressor options.
540317959322c665d211788f07227abcba61984ec88plougher	 *
541317959322c665d211788f07227abcba61984ec88plougher	 * Note, if there's no compressor options present, the compressor
542317959322c665d211788f07227abcba61984ec88plougher	 * is still called to set the default options (the defaults may have
543317959322c665d211788f07227abcba61984ec88plougher	 * been changed by the user specifying options on the command
544317959322c665d211788f07227abcba61984ec88plougher	 * line which need to be over-ridden).
54547d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 *
54647d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * Compressor_extract_options is also used to ensure that
54747d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * we know how decompress a filesystem compressed with these
54847d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * compression options.
5495924372bba7ac923cca996e74716128a98f668afplougher	 */
5505924372bba7ac923cca996e74716128a98f668afplougher	if(SQUASHFS_COMP_OPTS(sBlk->flags)) {
551b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		bytes = read_block(fd, sizeof(*sBlk), NULL, 0, buffer);
5525924372bba7ac923cca996e74716128a98f668afplougher
5533d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher		if(bytes == 0) {
5542a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Failed to read compressor options from append "
5553d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher				"filesystem\n");
5562a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
5575924372bba7ac923cca996e74716128a98f668afplougher			goto failed_mount;
5583d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher		}
559317959322c665d211788f07227abcba61984ec88plougher	}
5605924372bba7ac923cca996e74716128a98f668afplougher
561317959322c665d211788f07227abcba61984ec88plougher	res = compressor_extract_options(comp, sBlk->block_size, buffer, bytes);
562317959322c665d211788f07227abcba61984ec88plougher	if(res == -1) {
563317959322c665d211788f07227abcba61984ec88plougher		ERROR("Compressor failed to set compressor options\n");
564317959322c665d211788f07227abcba61984ec88plougher		goto failed_mount;
5655924372bba7ac923cca996e74716128a98f668afplougher	}
5665924372bba7ac923cca996e74716128a98f668afplougher
567e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("Found a valid %sSQUASHFS superblock on %s.\n",
568e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
569bb98803edb506b6e99693892350ebeca99c6a3dfplougher	printf("\tCompression used %s\n", comp->name);
570e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tInodes are %scompressed\n",
571e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
572e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tData is %scompressed\n",
573e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
574e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFragments are %scompressed\n",
575e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : "");
576a10230e410599e3cf1c4ea7fa9a2ba11d4e8eaa1plougher	printf("\tXattrs are %scompressed\n",
577a10230e410599e3cf1c4ea7fa9a2ba11d4e8eaa1plougher		SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? "un" : "");
578e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFragments are %spresent in the filesystem\n",
579e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : "");
5809077fad8779e259fa03326b567644374e98ff171Phillip Lougher	printf("\tAlways-use-fragments option is %sspecified\n",
581e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not ");
582e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tDuplicates are %sremoved\n",
583e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not ");
5841031268dc09bac693d8c6d8e913cbf984f0592f5plougher	printf("\tXattrs are %sstored\n",
5851031268dc09bac693d8c6d8e913cbf984f0592f5plougher		SQUASHFS_NO_XATTRS(sBlk->flags) ? "not " : "");
586e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n",
587e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		sBlk->bytes_used / 1024.0, sBlk->bytes_used
588e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		/ (1024.0 * 1024.0));
5891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tBlock size %d\n", sBlk->block_size);
5901f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tNumber of fragments %d\n", sBlk->fragments);
5911f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tNumber of inodes %d\n", sBlk->inodes);
5921b899fc316f7eba7a31da12dc0c9b69ada441059plougher	printf("\tNumber of ids %d\n", sBlk->no_ids);
5931f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start);
594e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	TRACE("sBlk->directory_table_start %llx\n",
595e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		sBlk->directory_table_start);
5961b899fc316f7eba7a31da12dc0c9b69ada441059plougher	TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start);
5971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start);
598f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher	TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
5999c0688ef8954e7e335a62479ba0408d585d47853plougher	TRACE("sBlk->xattr_id_table_start %llx\n", sBlk->xattr_id_table_start);
6001f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\n");
6011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
60234c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	return comp;
6031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherfailed_mount:
60534c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	return NULL;
6061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
6071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6081f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
609e69aac119c4660c567d5159729b9875c3330e4bbplougherunsigned char *squashfs_readdir(int fd, int root_entries,
610e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int directory_start_block, int offset, int size,
61164e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher	unsigned int *last_directory_block, struct squashfs_super_block *sBlk,
612e69aac119c4660c567d5159729b9875c3330e4bbplougher	void (push_directory_entry)(char *, squashfs_inode, int, int))
6131f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
614520e1a144c9a6c957754f93dc8830f884fe5669bplougher	struct squashfs_dir_header dirh;
6159b393553bbca1d7efc755a4b73e64407a526ef11plougher	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]
61646aefa984f924b2187e8f104fafed15899200237plougher		__attribute__ ((aligned));
6179b393553bbca1d7efc755a4b73e64407a526ef11plougher	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
6181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned char *directory_table = NULL;
619df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher	int byte, bytes = 0, dir_count;
620e69aac119c4660c567d5159729b9875c3330e4bbplougher	long long start = sBlk->directory_table_start + directory_start_block,
621e69aac119c4660c567d5159729b9875c3330e4bbplougher		last_start_block = start;
6221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	size += offset;
624e69aac119c4660c567d5159729b9875c3330e4bbplougher	directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) &
625e69aac119c4660c567d5159729b9875c3330e4bbplougher		~(SQUASHFS_METADATA_SIZE - 1));
626e69aac119c4660c567d5159729b9875c3330e4bbplougher	if(directory_table == NULL)
6279facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
6289facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
6291f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	while(bytes < size) {
630a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher		int expected = (size - bytes) >= SQUASHFS_METADATA_SIZE ?
631a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher			SQUASHFS_METADATA_SIZE : 0;
632a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher
633e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("squashfs_readdir: reading block 0x%llx, bytes read so "
634e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			"far %d\n", start, bytes);
635a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher
6361f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		last_start_block = start;
637a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher		byte = read_block(fd, start, &start, expected, directory_table + bytes);
638e69aac119c4660c567d5159729b9875c3330e4bbplougher		if(byte == 0) {
6392a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Failed to read directory\n");
6402a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
6411f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			free(directory_table);
6421f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			return NULL;
6431f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
644df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher		bytes += byte;
6451f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
6461f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6471f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(!root_entries)
6481f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto all_done;
6491f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6501f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	bytes = offset;
6511f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher 	while(bytes < size) {
652690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);
6531f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6541f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		dir_count = dirh.count + 1;
655e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("squashfs_readdir: Read directory header @ byte position "
656e69aac119c4660c567d5159729b9875c3330e4bbplougher			"0x%x, 0x%x directory entries\n", bytes, dir_count);
6571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		bytes += sizeof(dirh);
6581f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6591f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		while(dir_count--) {
660690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);
6611f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			bytes += sizeof(*dire);
6621f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
663e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			memcpy(dire->name, directory_table + bytes,
664e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->size + 1);
6651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			dire->name[dire->size + 1] = '\0';
666e69aac119c4660c567d5159729b9875c3330e4bbplougher			TRACE("squashfs_readdir: pushing directory entry %s, "
667e69aac119c4660c567d5159729b9875c3330e4bbplougher				"inode %x:%x, type 0x%x\n", dire->name,
668e69aac119c4660c567d5159729b9875c3330e4bbplougher				dirh.start_block, dire->offset, dire->type);
669e69aac119c4660c567d5159729b9875c3330e4bbplougher			push_directory_entry(dire->name,
670e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				SQUASHFS_MKINODE(dirh.start_block,
671e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->offset), dirh.inode_number +
672e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->inode_number, dire->type);
6731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			bytes += dire->size + 1;
6741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
6751f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
6761f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6771f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherall_done:
678e69aac119c4660c567d5159729b9875c3330e4bbplougher	*last_directory_block = (unsigned int) last_start_block -
679e69aac119c4660c567d5159729b9875c3330e4bbplougher		sBlk->directory_table_start;
6801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return directory_table;
6811f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
6821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6831f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
68464e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherunsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk)
6851b899fc316f7eba7a31da12dc0c9b69ada441059plougher{
6861b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids);
6871b899fc316f7eba7a31da12dc0c9b69ada441059plougher	long long index[indexes];
6881b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids);
68961343797593e92ad2cf75b221398c138e1fee058plougher	unsigned int *id_table;
6901d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res, i;
6911b899fc316f7eba7a31da12dc0c9b69ada441059plougher
6921b899fc316f7eba7a31da12dc0c9b69ada441059plougher	id_table = malloc(bytes);
6939facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(id_table == NULL)
6949facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
6951b899fc316f7eba7a31da12dc0c9b69ada441059plougher
6961d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->id_table_start,
6973306cb2b54a60a32664617118336ac141e1471b6plougher		SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index);
6981d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
6999f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read id table index\n");
7009f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
7011d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(id_table);
7021d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return NULL;
7031d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
7041d065e9f3c6d22a629134837a55538fb8619cfb4plougher
70561343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);
7061b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7071b899fc316f7eba7a31da12dc0c9b69ada441059plougher	for(i = 0; i < indexes; i++) {
708197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
709197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher					bytes & (SQUASHFS_METADATA_SIZE - 1);
710197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher		int length = read_block(fd, index[i], NULL, expected,
711e69aac119c4660c567d5159729b9875c3330e4bbplougher			((unsigned char *) id_table) +
712923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
713e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
714e69aac119c4660c567d5159729b9875c3330e4bbplougher			index[i], length);
715730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
716730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read id table block %d, from 0x%llx, "
717730ef508553ce562277b5d34fd272716e7ed6f13plougher				"length %d\n", i, index[i], length);
7182a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
719730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(id_table);
720730ef508553ce562277b5d34fd272716e7ed6f13plougher			return NULL;
721730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
7221b899fc316f7eba7a31da12dc0c9b69ada441059plougher	}
7231b899fc316f7eba7a31da12dc0c9b69ada441059plougher
72461343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);
7251b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7261b899fc316f7eba7a31da12dc0c9b69ada441059plougher	for(i = 0; i < sBlk->no_ids; i++) {
7271b899fc316f7eba7a31da12dc0c9b69ada441059plougher		TRACE("Adding id %d to id tables\n", id_table[i]);
7281b899fc316f7eba7a31da12dc0c9b69ada441059plougher		create_id(id_table[i]);
7291b899fc316f7eba7a31da12dc0c9b69ada441059plougher	}
7301b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7311b899fc316f7eba7a31da12dc0c9b69ada441059plougher	return id_table;
7321b899fc316f7eba7a31da12dc0c9b69ada441059plougher}
7331b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7341b899fc316f7eba7a31da12dc0c9b69ada441059plougher
73564e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherint read_fragment_table(int fd, struct squashfs_super_block *sBlk,
7368ed84b96ca36da8147993935b951918359d8f20aplougher	struct squashfs_fragment_entry **fragment_table)
7371f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
738852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int res, i;
739852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int bytes = SQUASHFS_FRAGMENT_BYTES(sBlk->fragments);
740852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);
7412625a3d8f39b94c4841bd605361f4b575b0dc1a5plougher	long long fragment_table_index[indexes];
7421f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
743e69aac119c4660c567d5159729b9875c3330e4bbplougher	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
744e69aac119c4660c567d5159729b9875c3330e4bbplougher		"from 0x%llx\n", sBlk->fragments, indexes,
745e69aac119c4660c567d5159729b9875c3330e4bbplougher		sBlk->fragment_table_start);
746852db8287892bb34537830311de63c0cc5563783Phillip Lougher
7471f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->fragments == 0)
7481f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		return 1;
7491f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
750852db8287892bb34537830311de63c0cc5563783Phillip Lougher	*fragment_table = malloc(bytes);
7519facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(*fragment_table == NULL)
7529facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
7531f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7541d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->fragment_table_start,
755e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments),
7563306cb2b54a60a32664617118336ac141e1471b6plougher		fragment_table_index);
7571d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
7589f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read fragment table index\n");
7599f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
7601d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(*fragment_table);
7611d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
7621d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
7631d065e9f3c6d22a629134837a55538fb8619cfb4plougher
76461343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);
7651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7661f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	for(i = 0; i < indexes; i++) {
767852db8287892bb34537830311de63c0cc5563783Phillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
768852db8287892bb34537830311de63c0cc5563783Phillip Lougher					bytes & (SQUASHFS_METADATA_SIZE - 1);
769852db8287892bb34537830311de63c0cc5563783Phillip Lougher		int length = read_block(fd, fragment_table_index[i], NULL,
770852db8287892bb34537830311de63c0cc5563783Phillip Lougher			expected, ((unsigned char *) *fragment_table) +
771923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
772e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
773e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			i, fragment_table_index[i], length);
774730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
775730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read fragment table block %d, from "
776730ef508553ce562277b5d34fd272716e7ed6f13plougher				"0x%llx, length %d\n", i,
777730ef508553ce562277b5d34fd272716e7ed6f13plougher				fragment_table_index[i], length);
7782a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
779730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(*fragment_table);
780730ef508553ce562277b5d34fd272716e7ed6f13plougher			return 0;
781730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
7821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
7831f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
78461343797593e92ad2cf75b221398c138e1fee058plougher	for(i = 0; i < sBlk->fragments; i++)
78561343797593e92ad2cf75b221398c138e1fee058plougher		SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]);
7861f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7871f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return 1;
7881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
7891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7901f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
79164e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherint read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk,
792e69aac119c4660c567d5159729b9875c3330e4bbplougher	squashfs_inode **inode_lookup_table)
7930e45365737bf5283627e32253f2279c4d9fa32d0plougher{
7940e45365737bf5283627e32253f2279c4d9fa32d0plougher	int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes);
7950e45365737bf5283627e32253f2279c4d9fa32d0plougher	int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes);
7960e45365737bf5283627e32253f2279c4d9fa32d0plougher	long long index[indexes];
7971d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res, i;
7980e45365737bf5283627e32253f2279c4d9fa32d0plougher
7990e45365737bf5283627e32253f2279c4d9fa32d0plougher	if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK)
8000e45365737bf5283627e32253f2279c4d9fa32d0plougher		return 1;
8010e45365737bf5283627e32253f2279c4d9fa32d0plougher
802e69aac119c4660c567d5159729b9875c3330e4bbplougher	*inode_lookup_table = malloc(lookup_bytes);
8039facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(*inode_lookup_table == NULL)
8049facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
8050e45365737bf5283627e32253f2279c4d9fa32d0plougher
8061d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->lookup_table_start,
8073306cb2b54a60a32664617118336ac141e1471b6plougher		SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index);
8081d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
8099f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read inode lookup table index\n");
8109f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
8111d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(*inode_lookup_table);
8121d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
8131d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
8141d065e9f3c6d22a629134837a55538fb8619cfb4plougher
81561343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_LONG_LONGS(index, indexes);
8160e45365737bf5283627e32253f2279c4d9fa32d0plougher
8170e45365737bf5283627e32253f2279c4d9fa32d0plougher	for(i = 0; i <  indexes; i++) {
818751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
819751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher				lookup_bytes & (SQUASHFS_METADATA_SIZE - 1);
820751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher		int length = read_block(fd, index[i], NULL, expected,
821e69aac119c4660c567d5159729b9875c3330e4bbplougher			((unsigned char *) *inode_lookup_table) +
822923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
823e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("Read inode lookup table block %d, from 0x%llx, length "
824e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			"%d\n", i, index[i], length);
825730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
826730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read inode lookup table block %d, "
827730ef508553ce562277b5d34fd272716e7ed6f13plougher				"from 0x%llx, length %d\n", i, index[i],
828730ef508553ce562277b5d34fd272716e7ed6f13plougher				length);
8292a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
830730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(*inode_lookup_table);
831730ef508553ce562277b5d34fd272716e7ed6f13plougher			return 0;
832730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
8330e45365737bf5283627e32253f2279c4d9fa32d0plougher	}
8340e45365737bf5283627e32253f2279c4d9fa32d0plougher
83561343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);
8360e45365737bf5283627e32253f2279c4d9fa32d0plougher
8370e45365737bf5283627e32253f2279c4d9fa32d0plougher	return 1;
8380e45365737bf5283627e32253f2279c4d9fa32d0plougher}
8390e45365737bf5283627e32253f2279c4d9fa32d0plougher
8400e45365737bf5283627e32253f2279c4d9fa32d0plougher
84164e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherlong long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk,
842e69aac119c4660c567d5159729b9875c3330e4bbplougher	char **cinode_table, char **data_cache, char **cdirectory_table,
843e69aac119c4660c567d5159729b9875c3330e4bbplougher	char **directory_data_cache, unsigned int *last_directory_block,
844e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size,
845e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *root_inode_size, unsigned int *inode_dir_start_block,
846e69aac119c4660c567d5159729b9875c3330e4bbplougher	int *file_count, int *sym_count, int *dev_count, int *dir_count,
847e69aac119c4660c567d5159729b9875c3330e4bbplougher	int *fifo_count, int *sock_count, long long *uncompressed_file,
848e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
849e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int *inode_dir_inode_number,
850e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int *inode_dir_parent_inode,
851e69aac119c4660c567d5159729b9875c3330e4bbplougher	void (push_directory_entry)(char *, squashfs_inode, int, int),
8528ed84b96ca36da8147993935b951918359d8f20aplougher	struct squashfs_fragment_entry **fragment_table,
853e69aac119c4660c567d5159729b9875c3330e4bbplougher	squashfs_inode **inode_lookup_table)
8541f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
855096135f7430824033f597e47906a24d087f47a34Phillip Lougher	unsigned char *inode_table = NULL, *directory_table = NULL;
856e69aac119c4660c567d5159729b9875c3330e4bbplougher	long long start = sBlk->inode_table_start;
857e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	long long end = sBlk->directory_table_start;
858e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	long long root_inode_start = start +
8591f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		SQUASHFS_INODE_BLK(sBlk->root_inode);
860e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int root_inode_offset =
861e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		SQUASHFS_INODE_OFFSET(sBlk->root_inode);
8621a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	unsigned int root_inode_block;
8638973a12943b86e759a6391995271fa620d73483fplougher	union squashfs_inode_header inode;
864096135f7430824033f597e47906a24d087f47a34Phillip Lougher	unsigned int *id_table = NULL;
8651d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res;
8661f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8671f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("Scanning existing filesystem...\n");
8681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
869570f436c85a99435180a3ec9aeb1c94135ab0e77plougher	if(get_xattrs(fd, sBlk) == 0)
870570f436c85a99435180a3ec9aeb1c94135ab0e77plougher		goto error;
871570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
8724c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher	if(read_fragment_table(fd, sBlk, fragment_table) == 0)
8731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto error;
8741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8750e45365737bf5283627e32253f2279c4d9fa32d0plougher	if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0)
8760e45365737bf5283627e32253f2279c4d9fa32d0plougher		goto error;
8770e45365737bf5283627e32253f2279c4d9fa32d0plougher
8781b899fc316f7eba7a31da12dc0c9b69ada441059plougher	id_table = read_id_table(fd, sBlk);
8791b899fc316f7eba7a31da12dc0c9b69ada441059plougher	if(id_table == NULL)
8801b899fc316f7eba7a31da12dc0c9b69ada441059plougher		goto error;
8811b899fc316f7eba7a31da12dc0c9b69ada441059plougher
88296eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher	res = scan_inode_table(fd, start, end, root_inode_start,
88396eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		root_inode_offset, sBlk, &inode, &inode_table,
88496eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		&root_inode_block, root_inode_size, uncompressed_file,
88596eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		uncompressed_directory, file_count, sym_count, dev_count,
88696eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		dir_count, fifo_count, sock_count, id_table);
8871a734af8bd761a7737b56a55a9de04f3753500acPhillip Lougher	if(res == 0)
8881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto error;
8891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8901f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	*uncompressed_inode = root_inode_block;
8911f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
892e69aac119c4660c567d5159729b9875c3330e4bbplougher	if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
893e69aac119c4660c567d5159729b9875c3330e4bbplougher			inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
8941f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
8951f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_start_block = inode.dir.start_block;
8961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_offset = inode.dir.offset;
897058eae41952c33345bd0ef290aea8eef37f3ca92plougher			*inode_dir_file_size = inode.dir.file_size - 3;
898df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_inode_number = inode.dir.inode_number;
899df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_parent_inode = inode.dir.parent_inode;
9001f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		} else {
9011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_start_block = inode.ldir.start_block;
9021f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_offset = inode.ldir.offset;
903058eae41952c33345bd0ef290aea8eef37f3ca92plougher			*inode_dir_file_size = inode.ldir.file_size - 3;
904df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_inode_number = inode.ldir.inode_number;
905df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_parent_inode = inode.ldir.parent_inode;
9061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
9071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
908e69aac119c4660c567d5159729b9875c3330e4bbplougher		directory_table = squashfs_readdir(fd, !root_name,
909e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_start_block, *inode_dir_offset,
910e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_file_size, last_directory_block, sBlk,
911e69aac119c4660c567d5159729b9875c3330e4bbplougher			push_directory_entry);
9124d7c0724196a5fce8fefa6ee923c79be7c94301bPhillip Lougher		if(directory_table == NULL)
9131f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			goto error;
9141f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
9151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		root_inode_start -= start;
916169d54f8cd07949d5708ff6ca7d48a06185ff604plougher		*cinode_table = malloc(root_inode_start);
9179facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*cinode_table == NULL)
9189facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9199facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
9201d065e9f3c6d22a629134837a55538fb8619cfb4plougher	       	res = read_fs_bytes(fd, start, root_inode_start, *cinode_table);
9219f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		if(res == 0) {
9229f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Failed to read inode table\n");
9239f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Filesystem corrupted?\n");
9241d065e9f3c6d22a629134837a55538fb8619cfb4plougher			goto error;
9259f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		}
9261f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
927e69aac119c4660c567d5159729b9875c3330e4bbplougher		*cdirectory_table = malloc(*last_directory_block);
9289facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*cdirectory_table == NULL)
9299facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9309facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
9311d065e9f3c6d22a629134837a55538fb8619cfb4plougher		res = read_fs_bytes(fd, sBlk->directory_table_start,
932e69aac119c4660c567d5159729b9875c3330e4bbplougher			*last_directory_block, *cdirectory_table);
9339f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		if(res == 0) {
9349f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Failed to read directory table\n");
9359451938650abe45e8714660f420c0546ccb7a6aaPhillip Lougher			ERROR("Filesystem corrupted?\n");
9361d065e9f3c6d22a629134837a55538fb8619cfb4plougher			goto error;
9379f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		}
9381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
939e69aac119c4660c567d5159729b9875c3330e4bbplougher		*data_cache = malloc(root_inode_offset + *root_inode_size);
9409facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*data_cache == NULL)
9419facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9429facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
943e69aac119c4660c567d5159729b9875c3330e4bbplougher		memcpy(*data_cache, inode_table + root_inode_block,
944e69aac119c4660c567d5159729b9875c3330e4bbplougher			root_inode_offset + *root_inode_size);
945e69aac119c4660c567d5159729b9875c3330e4bbplougher
946e69aac119c4660c567d5159729b9875c3330e4bbplougher		*directory_data_cache = malloc(*inode_dir_offset +
947e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_file_size);
9489facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*directory_data_cache == NULL)
9499facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9509facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
951e69aac119c4660c567d5159729b9875c3330e4bbplougher		memcpy(*directory_data_cache, directory_table,
952e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_offset + *inode_dir_file_size);
9531f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
954096135f7430824033f597e47906a24d087f47a34Phillip Lougher		free(id_table);
9551f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		free(inode_table);
9561f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		free(directory_table);
9571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		return sBlk->inode_table_start;
9581f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
9591f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
9601f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughererror:
961096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(id_table);
962096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(inode_table);
963096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(directory_table);
9641f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return 0;
9651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
966