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,
6b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher * 2012, 2013, 2014
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
55b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougherint read_block(int fd, long long start, long long *next, int expected,
56b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher								void *block)
571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
581f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned short c_byte;
59b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	int res, compressed;
60b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	int outlen = expected ? expected : SQUASHFS_METADATA_SIZE;
611f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
62b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/* Read block size */
633306cb2b54a60a32664617118336ac141e1471b6plougher	res = read_fs_bytes(fd, start, 2, &c_byte);
641d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0)
651d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
661d065e9f3c6d22a629134837a55538fb8619cfb4plougher
6761343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
68b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	compressed = SQUASHFS_COMPRESSED(c_byte);
69b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
701f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
71b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/*
72b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * The block size should not be larger than
73b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * the uncompressed size (or max uncompressed size if
74b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * expected is 0)
75b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 */
76b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if (c_byte > outlen)
77b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return 0;
78b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
79b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(compressed) {
80b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		char buffer[c_byte];
81b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		int error;
821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
83540c7abc405a7a26373d5299e77122eae1365c56plougher		res = read_fs_bytes(fd, start + 2, c_byte, buffer);
841d065e9f3c6d22a629134837a55538fb8619cfb4plougher		if(res == 0)
851d065e9f3c6d22a629134837a55538fb8619cfb4plougher			return 0;
861f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
87b48442b2e37b3cb7efbffb032968f115eec7963cplougher		res = compressor_uncompress(comp, block, buffer, c_byte,
88b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher			outlen, &error);
899f1e0e214eaff51604105b88153f2d77bc398158plougher		if(res == -1) {
909f1e0e214eaff51604105b88153f2d77bc398158plougher			ERROR("%s uncompress failed with error code %d\n",
919f1e0e214eaff51604105b88153f2d77bc398158plougher				comp->name, error);
921f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			return 0;
931f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
941f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	} else {
95540c7abc405a7a26373d5299e77122eae1365c56plougher		res = read_fs_bytes(fd, start + 2, c_byte, block);
961d065e9f3c6d22a629134837a55538fb8619cfb4plougher		if(res == 0)
971d065e9f3c6d22a629134837a55538fb8619cfb4plougher			return 0;
98b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		res = c_byte;
991f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
100b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
101b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(next)
102b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		*next = start + 2 + c_byte;
103b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
104b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	/*
105b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * if expected, then check the (uncompressed) return data
106b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 * is of the expected size
107b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	 */
108b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	if(expected && expected != res)
109b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return 0;
110b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher	else
111b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		return res;
1127e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher}
113b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
114b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher
1157e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher#define NO_BYTES(SIZE) \
1167e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	(bytes - (cur_ptr - *inode_table) < (SIZE))
1171f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1187e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher#define NO_INODE_BYTES(INODE) NO_BYTES(sizeof(struct INODE))
1191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1201b899fc316f7eba7a31da12dc0c9b69ada441059plougherint scan_inode_table(int fd, long long start, long long end,
1211b899fc316f7eba7a31da12dc0c9b69ada441059plougher	long long root_inode_start, int root_inode_offset,
122e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	struct squashfs_super_block *sBlk, union squashfs_inode_header
123e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	*dir_inode, unsigned char **inode_table, unsigned int *root_inode_block,
1241b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *root_inode_size, long long *uncompressed_file,
1251b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *uncompressed_directory, int *file_count, int *sym_count,
1261b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int *dev_count, int *dir_count, int *fifo_count, int *sock_count,
1271b899fc316f7eba7a31da12dc0c9b69ada441059plougher	unsigned int *id_table)
1281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
1291f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned char *cur_ptr;
1307e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	int byte, files = 0;
1317e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	unsigned int directory_start_block, bytes = 0, size = 0;
1327e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	struct squashfs_base_inode_header base;
1331f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
134e69aac119c4660c567d5159729b9875c3330e4bbplougher	TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start "
135e69aac119c4660c567d5159729b9875c3330e4bbplougher		"0x%llx\n", start, end, root_inode_start);
136e69aac119c4660c567d5159729b9875c3330e4bbplougher
137125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	*root_inode_block = UINT_MAX;
1381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	while(start < end) {
1391f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		if(start == root_inode_start) {
140e69aac119c4660c567d5159729b9875c3330e4bbplougher			TRACE("scan_inode_table: read compressed block 0x%llx "
141e69aac119c4660c567d5159729b9875c3330e4bbplougher				"containing root inode\n", start);
1421f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*root_inode_block = bytes;
1431f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
144e69aac119c4660c567d5159729b9875c3330e4bbplougher		if(size - bytes < SQUASHFS_METADATA_SIZE) {
145e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_table = realloc(*inode_table, size
146e69aac119c4660c567d5159729b9875c3330e4bbplougher				+= SQUASHFS_METADATA_SIZE);
147e69aac119c4660c567d5159729b9875c3330e4bbplougher			if(*inode_table == NULL)
1489facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
149e69aac119c4660c567d5159729b9875c3330e4bbplougher		}
1504c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher		TRACE("scan_inode_table: reading block 0x%llx\n", start);
151b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		byte = read_block(fd, start, &start, 0, *inode_table + bytes);
1527e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(byte == 0)
15345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
1542b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher
1554c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher		bytes += byte;
1562b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher
1572b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		/* If this is not the last metadata block in the inode table
1582b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * then it should be SQUASHFS_METADATA_SIZE in size.
1592b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * Note, we can't use expected in read_block() above for this
1602b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * because we don't know if this is the last block until
1612b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 * after reading.
1622b7242f3271eabb76c6c8ecdfeb9db2e97376488Phillip Lougher		 */
1637e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(start != end && byte != SQUASHFS_METADATA_SIZE)
16445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
1651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
1661f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1671f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	/*
168125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * We expect to have found the metadata block containing the
169125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * root inode in the above inode_table metadata block scan.  If it
170125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 * hasn't been found then the filesystem is corrupted
171125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	 */
1727e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if(*root_inode_block == UINT_MAX)
17345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
1747e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
1757e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	/*
1767e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * The number of bytes available after the root inode medata block
1777e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * should be at least the root inode offset + the size of a
1787e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * regular directory inode, if not the filesystem is corrupted
1797e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *
1807e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	+-----------------------+-----------------------+
1817e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	| 			|        directory	|
1827e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	|			|          inode	|
1837e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	+-----------------------+-----------------------+
1847e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	^			^			^
1857e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 *	*root_inode_block	root_inode_offset	bytes
1867e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 */
1877e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if((bytes - *root_inode_block) < (root_inode_offset +
1887e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			sizeof(struct squashfs_dir_inode_header)))
18945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
190125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher
191125de73c204b2b92c03ee9bff16dd595e71656afPhillip Lougher	/*
192e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * Read last inode entry which is the root directory inode, and obtain
193e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * the last directory start block index.  This is used when calculating
194e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * the total uncompressed directory size.  The directory bytes in the
195e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	 * last * block will be counted as normal.
1961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	 *
1977e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * Note, the previous check ensures the following calculation won't
1987e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	 * underflow, and we won't access beyond the buffer
1991f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	 */
2001f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	*root_inode_size = bytes - (*root_inode_block + root_inode_offset);
2011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	bytes = *root_inode_block + root_inode_offset;
202690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher	SQUASHFS_SWAP_DIR_INODE_HEADER(*inode_table + bytes, &dir_inode->dir);
2037e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
2047e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE)
2051f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		directory_start_block = dir_inode->dir.start_block;
2067e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	else if(dir_inode->base.inode_type == SQUASHFS_LDIR_TYPE) {
2077e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(*root_inode_size < sizeof(struct squashfs_ldir_inode_header))
2087e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			/* corrupted filesystem */
20945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
210690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_LDIR_INODE_HEADER(*inode_table + bytes,
211690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			&dir_inode->ldir);
2121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		directory_start_block = dir_inode->ldir.start_block;
2137e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher	} else
2147e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		/* bad type, corrupted filesystem */
21545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		goto corrupted;
2167e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
2171b899fc316f7eba7a31da12dc0c9b69ada441059plougher	get_uid(id_table[dir_inode->base.uid]);
2181b899fc316f7eba7a31da12dc0c9b69ada441059plougher	get_guid(id_table[dir_inode->base.guid]);
2191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
220b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher	/* allocate fragment to file mapping table */
221b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher	file_mapping = calloc(sBlk->fragments, sizeof(struct append_file *));
222b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher	if(file_mapping == NULL)
223b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher		MEM_ERROR();
224b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher
2251f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) {
2267e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		if(NO_INODE_BYTES(squashfs_base_inode_header))
2277e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			/* corrupted filesystem */
22845f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
2297e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
230690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_BASE_INODE_HEADER(cur_ptr, &base);
2311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
232e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("scan_inode_table: processing inode @ byte position "
233363ddaa1fcfd7e2bb186cb78990c43e491ea981dplougher			"0x%x, type 0x%x\n",
234363ddaa1fcfd7e2bb186cb78990c43e491ea981dplougher			(unsigned int) (cur_ptr - *inode_table),
2357e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher			base.inode_type);
2361b899fc316f7eba7a31da12dc0c9b69ada441059plougher
2377e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		get_uid(id_table[base.uid]);
2387e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		get_guid(id_table[base.guid]);
2391b899fc316f7eba7a31da12dc0c9b69ada441059plougher
2407e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher		switch(base.inode_type) {
241e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_FILE_TYPE: {
242e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_reg_inode_header inode;
243e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int frag_bytes, blocks, i;
244e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			long long start, file_bytes = 0;
245e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			unsigned int *block_list;
246e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
247e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_reg_inode_header))
248e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
24945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
2507e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
251690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_REG_INODE_HEADER(cur_ptr, &inode);
2527e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
253e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ?
254e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				0 : inode.file_size % sBlk->block_size;
255e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			blocks = inode.fragment == SQUASHFS_INVALID_FRAG ?
256e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				(inode.file_size + sBlk->block_size - 1) >>
257e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log : inode.file_size >>
258e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log;
259e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			start = inode.start_block;
2607e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
261e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			TRACE("scan_inode_table: regular file, file_size %d, "
262e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				"blocks %d\n", inode.file_size, blocks);
2631f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
264e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_BYTES(blocks * sizeof(unsigned int)))
265e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
26645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
2671f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
268e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			block_list = malloc(blocks * sizeof(unsigned int));
2699facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			if(block_list == NULL)
2709facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
2717e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
272e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(inode);
273690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);
2747e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
275e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			*uncompressed_file += inode.file_size;
276e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*file_count) ++;
277058eae41952c33345bd0ef290aea8eef37f3ca92plougher
278e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < blocks; i++)
279e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				file_bytes +=
280e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					SQUASHFS_COMPRESSED_SIZE_BLOCK
281e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher								(block_list[i]);
282058eae41952c33345bd0ef290aea8eef37f3ca92plougher
283b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher			if(inode.fragment != SQUASHFS_INVALID_FRAG &&
28498ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher					inode.fragment >= sBlk->fragments) {
28598ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher				free(block_list);
286b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher				goto corrupted;
28798ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher			}
288b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher
289e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			add_file(start, inode.file_size, file_bytes,
290e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				block_list, blocks, inode.fragment,
291e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.offset, frag_bytes);
292e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
293e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += blocks * sizeof(unsigned int);
294e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
295e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
296e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LREG_TYPE: {
297e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_lreg_inode_header inode;
298e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int frag_bytes, blocks, i;
299e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			long long start, file_bytes = 0;
300e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			unsigned int *block_list;
301e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
302e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lreg_inode_header))
303e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
30445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
305f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher
306690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_LREG_INODE_HEADER(cur_ptr, &inode);
3077e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
308e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ?
309e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				0 : inode.file_size % sBlk->block_size;
310e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			blocks = inode.fragment == SQUASHFS_INVALID_FRAG ?
311e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				(inode.file_size + sBlk->block_size - 1) >>
312e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log : inode.file_size >>
313e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				sBlk->block_log;
314e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			start = inode.start_block;
315570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
316e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			TRACE("scan_inode_table: extended regular "
317e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				"file, file_size %lld, blocks %d\n",
318e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.file_size, blocks);
319570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
320e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_BYTES(blocks * sizeof(unsigned int)))
321e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
32245f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
3237e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
324e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			block_list = malloc(blocks * sizeof(unsigned int));
3259facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			if(block_list == NULL)
3269facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher				MEM_ERROR();
3271f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
328e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(inode);
329690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);
3301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
331e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			*uncompressed_file += inode.file_size;
332e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*file_count) ++;
3337e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
334e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < blocks; i++)
335e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				file_bytes +=
336e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					SQUASHFS_COMPRESSED_SIZE_BLOCK
337e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher								(block_list[i]);
3387e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
339b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher			if(inode.fragment != SQUASHFS_INVALID_FRAG &&
34098ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher					inode.fragment >= sBlk->fragments) {
34198ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher				free(block_list);
342b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher				goto corrupted;
34398ef7c94502920658f49fbaadbf7319eb4a04124Phillip Lougher			}
344b4fc3bf1abd7cf8d65cc68ad742a254d76f5da09Phillip Lougher
345e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			add_file(start, inode.file_size, file_bytes,
346e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				block_list, blocks, inode.fragment,
347e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				inode.offset, frag_bytes);
3487e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
349e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += blocks * sizeof(unsigned int);
350e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
351e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
352e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_SYMLINK_TYPE:
353e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LSYMLINK_TYPE: {
354e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_symlink_inode_header inode;
35561343797593e92ad2cf75b221398c138e1fee058plougher
356e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_symlink_inode_header))
357e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
35845f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
3597e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
360690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_SYMLINK_INODE_HEADER(cur_ptr, &inode);
3617e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
362e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sym_count) ++;
3637e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
364e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if (inode.inode_type == SQUASHFS_LSYMLINK_TYPE) {
365e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(inode.symlink_size +
366e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher							sizeof(unsigned int)))
3677e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
36845f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
369e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(inode) + inode.symlink_size +
370e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher							sizeof(unsigned int);
371e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			} else {
372e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(inode.symlink_size))
3737e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
37445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
375e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(inode) + inode.symlink_size;
376e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			}
377e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
378e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
379e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_DIR_TYPE: {
380e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_dir_inode_header dir_inode;
3817e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
382e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_dir_inode_header))
383e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
38445f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
385e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
386690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_DIR_INODE_HEADER(cur_ptr, &dir_inode);
387e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
388e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(dir_inode.start_block < directory_start_block)
389e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				*uncompressed_directory += dir_inode.file_size;
390e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
391e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dir_count) ++;
392e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_dir_inode_header);
393e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
394e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
395e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LDIR_TYPE: {
396e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			struct squashfs_ldir_inode_header dir_inode;
397e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			int i;
3987e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
399e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ldir_inode_header))
400e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
40145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
402e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
403690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_LDIR_INODE_HEADER(cur_ptr, &dir_inode);
404e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
405e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(dir_inode.start_block < directory_start_block)
406e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				*uncompressed_directory += dir_inode.file_size;
407e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
408e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dir_count) ++;
409e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ldir_inode_header);
410e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
411e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			for(i = 0; i < dir_inode.i_count; i++) {
412e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				struct squashfs_dir_index index;
413e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
414e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(sizeof(index)))
4157e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
41645f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
417e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
418690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher				SQUASHFS_SWAP_DIR_INDEX(cur_ptr, &index);
4197e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
420e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				if(NO_BYTES(index.size + 1))
4217e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher					/* corrupted filesystem */
42245f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher					goto corrupted;
4237e08fad7a62bdbbbe39e1248c3c4b05f5caf9e2cPhillip Lougher
424e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				cur_ptr += sizeof(index) + index.size + 1;
425e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			}
426e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
427e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		}
428e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_BLKDEV_TYPE:
429e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_CHRDEV_TYPE:
430e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_dev_inode_header))
431e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
43245f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
433e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
434e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dev_count) ++;
435e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_dev_inode_header);
436e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
437e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_LBLKDEV_TYPE:
438e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	case SQUASHFS_LCHRDEV_TYPE:
439e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ldev_inode_header))
440e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
44145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
442e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
443e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*dev_count) ++;
444e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ldev_inode_header);
445e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
446e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_FIFO_TYPE:
447e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ipc_inode_header))
448e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
44945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
450e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
451e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*fifo_count) ++;
452e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ipc_inode_header);
453e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
454e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LFIFO_TYPE:
455e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lipc_inode_header))
456e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
45745f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
458e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
459e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*fifo_count) ++;
460e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_lipc_inode_header);
461e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
462e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_SOCKET_TYPE:
463e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_ipc_inode_header))
464e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
46545f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
466e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
467e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sock_count) ++;
468e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_ipc_inode_header);
469e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
470e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher		case SQUASHFS_LSOCKET_TYPE:
471e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			if(NO_INODE_BYTES(squashfs_lipc_inode_header))
472e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher				/* corrupted filesystem */
47345f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher				goto corrupted;
474e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher
475e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			(*sock_count) ++;
476e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			cur_ptr += sizeof(struct squashfs_lipc_inode_header);
477e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			break;
478e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher	 	default:
479e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher			ERROR("Unknown inode type %d in scan_inode_table!\n",
480e465085a0a75ed749a9ec5edaff2ea5cd5b47997Phillip Lougher					base.inode_type);
48145f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher			goto corrupted;
4821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
4831f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
4841f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
4851a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	printf("Read existing filesystem, %d inodes scanned\n", files);
4861a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	return TRUE;
487058eae41952c33345bd0ef290aea8eef37f3ca92plougher
48845f78347049325b32c0ab96e6858f3f2bb993532Phillip Loughercorrupted:
48945f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher	ERROR("scan_inode_table: filesystem corruption detected in "
49045f78347049325b32c0ab96e6858f3f2bb993532Phillip Lougher		"scanning metadata\n");
491058eae41952c33345bd0ef290aea8eef37f3ca92plougher	free(*inode_table);
492058eae41952c33345bd0ef290aea8eef37f3ca92plougher	return FALSE;
4931f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
4941f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
4951f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
49664e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherstruct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source)
4971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
498317959322c665d211788f07227abcba61984ec88plougher	int res, bytes = 0;
499f6310758b1c84e5f7223425bfaaee97eb962a506plougher	char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));
5001d065e9f3c6d22a629134837a55538fb8619cfb4plougher
50164e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher	res = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block),
5023306cb2b54a60a32664617118336ac141e1471b6plougher		sBlk);
50363ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher	if(res == 0) {
50463ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher		ERROR("Can't find a SQUASHFS superblock on %s\n",
50563ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher				source);
50663ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher		ERROR("Wrong filesystem or filesystem is corrupted!\n");
5071d065e9f3c6d22a629134837a55538fb8619cfb4plougher		goto failed_mount;
50863ce1770edbdcc36ab48a1dba63af4636dcb69bdPhillip Lougher	}
5091d065e9f3c6d22a629134837a55538fb8619cfb4plougher
51061343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_SUPER_BLOCK(sBlk);
5111f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
5121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->s_magic != SQUASHFS_MAGIC) {
5132702e98268c66397751f9ed996a6460f216dba34plougher		if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP)
5142702e98268c66397751f9ed996a6460f216dba34plougher			ERROR("Pre 4.0 big-endian filesystem on %s, appending"
5152702e98268c66397751f9ed996a6460f216dba34plougher				" to this is unsupported\n", source);
5160372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher		else {
517e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			ERROR("Can't find a SQUASHFS superblock on %s\n",
518e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				source);
5190372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher			ERROR("Wrong filesystem or filesystem is corrupted!\n");
5200372aa056962a0dbdcbb45de9be23f522d645029Phillip Lougher		}
5212702e98268c66397751f9ed996a6460f216dba34plougher		goto failed_mount;
5221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
5231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
5241f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	/* Check the MAJOR & MINOR versions */
5251f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
526f83fbe8fc5e688b288f34865cc885a5711118221plougher		if(sBlk->s_major < 4)
527e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem."
528e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"  Appending\nto SQUASHFS %d.%d filesystems is "
529e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"not supported.  Please convert it to a "
530e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				"SQUASHFS 4 filesystem\n", source,
531e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				sBlk->s_major,
532e69aac119c4660c567d5159729b9875c3330e4bbplougher				sBlk->s_minor, sBlk->s_major, sBlk->s_minor);
5331f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		else
534e69aac119c4660c567d5159729b9875c3330e4bbplougher			ERROR("Filesystem on %s is %d.%d, which is a later "
535e69aac119c4660c567d5159729b9875c3330e4bbplougher				"filesystem version than I support\n",
536df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher				source, sBlk->s_major, sBlk->s_minor);
5371f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto failed_mount;
5381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
5391f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
54034c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	/* Check the compression type */
54134c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	comp = lookup_compressor_id(sBlk->compression);
54234c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	if(!comp->supported) {
54348c97065cf29dff24d01d94b39f4fdc6cef815f2Phillip Lougher		ERROR("Filesystem on %s uses %s compression, this is "
54434c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher			"unsupported by this version\n", source, comp->name);
545f09d9a6589de25eb4b9c9891277a717c1053a400plougher		ERROR("Compressors available:\n");
546764dab5cd71bda25bc755de08908dbbd58c1a450plougher		display_compressors("", "");
54734c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher		goto failed_mount;
54834c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	}
54934c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher
5505924372bba7ac923cca996e74716128a98f668afplougher	/*
5515924372bba7ac923cca996e74716128a98f668afplougher	 * Read extended superblock information from disk.
5525924372bba7ac923cca996e74716128a98f668afplougher	 *
5535924372bba7ac923cca996e74716128a98f668afplougher	 * Read compressor specific options from disk if present, and pass
5545924372bba7ac923cca996e74716128a98f668afplougher	 * to compressor to set compressor options.
555317959322c665d211788f07227abcba61984ec88plougher	 *
556317959322c665d211788f07227abcba61984ec88plougher	 * Note, if there's no compressor options present, the compressor
557317959322c665d211788f07227abcba61984ec88plougher	 * is still called to set the default options (the defaults may have
558317959322c665d211788f07227abcba61984ec88plougher	 * been changed by the user specifying options on the command
559317959322c665d211788f07227abcba61984ec88plougher	 * line which need to be over-ridden).
56047d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 *
56147d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * Compressor_extract_options is also used to ensure that
56247d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * we know how decompress a filesystem compressed with these
56347d52fe6f28cb8650ed8d1abb745137579f35e13Phillip Lougher	 * compression options.
5645924372bba7ac923cca996e74716128a98f668afplougher	 */
5655924372bba7ac923cca996e74716128a98f668afplougher	if(SQUASHFS_COMP_OPTS(sBlk->flags)) {
566b5db9ddc5eadd38b7a34b50ac64c9c4f61a551b2Phillip Lougher		bytes = read_block(fd, sizeof(*sBlk), NULL, 0, buffer);
5675924372bba7ac923cca996e74716128a98f668afplougher
5683d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher		if(bytes == 0) {
5692a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Failed to read compressor options from append "
5703d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher				"filesystem\n");
5712a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
5725924372bba7ac923cca996e74716128a98f668afplougher			goto failed_mount;
5733d5c06089c65e94ad819477d8a933f93476e8b7dPhillip Lougher		}
574317959322c665d211788f07227abcba61984ec88plougher	}
5755924372bba7ac923cca996e74716128a98f668afplougher
576317959322c665d211788f07227abcba61984ec88plougher	res = compressor_extract_options(comp, sBlk->block_size, buffer, bytes);
577317959322c665d211788f07227abcba61984ec88plougher	if(res == -1) {
578317959322c665d211788f07227abcba61984ec88plougher		ERROR("Compressor failed to set compressor options\n");
579317959322c665d211788f07227abcba61984ec88plougher		goto failed_mount;
5805924372bba7ac923cca996e74716128a98f668afplougher	}
5815924372bba7ac923cca996e74716128a98f668afplougher
582e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("Found a valid %sSQUASHFS superblock on %s.\n",
583e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
584bb98803edb506b6e99693892350ebeca99c6a3dfplougher	printf("\tCompression used %s\n", comp->name);
585e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tInodes are %scompressed\n",
586e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
587e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tData is %scompressed\n",
588e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
589e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFragments are %scompressed\n",
590e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : "");
591a10230e410599e3cf1c4ea7fa9a2ba11d4e8eaa1plougher	printf("\tXattrs are %scompressed\n",
592a10230e410599e3cf1c4ea7fa9a2ba11d4e8eaa1plougher		SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? "un" : "");
593e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFragments are %spresent in the filesystem\n",
594e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : "");
5959077fad8779e259fa03326b567644374e98ff171Phillip Lougher	printf("\tAlways-use-fragments option is %sspecified\n",
596e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not ");
597e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tDuplicates are %sremoved\n",
598e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not ");
5991031268dc09bac693d8c6d8e913cbf984f0592f5plougher	printf("\tXattrs are %sstored\n",
6001031268dc09bac693d8c6d8e913cbf984f0592f5plougher		SQUASHFS_NO_XATTRS(sBlk->flags) ? "not " : "");
601e69aac119c4660c567d5159729b9875c3330e4bbplougher	printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n",
602e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		sBlk->bytes_used / 1024.0, sBlk->bytes_used
603e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		/ (1024.0 * 1024.0));
6041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tBlock size %d\n", sBlk->block_size);
6051f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tNumber of fragments %d\n", sBlk->fragments);
6061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\tNumber of inodes %d\n", sBlk->inodes);
6071b899fc316f7eba7a31da12dc0c9b69ada441059plougher	printf("\tNumber of ids %d\n", sBlk->no_ids);
6081f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start);
609e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	TRACE("sBlk->directory_table_start %llx\n",
610e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		sBlk->directory_table_start);
6111b899fc316f7eba7a31da12dc0c9b69ada441059plougher	TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start);
6121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start);
613f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher	TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
6149c0688ef8954e7e335a62479ba0408d585d47853plougher	TRACE("sBlk->xattr_id_table_start %llx\n", sBlk->xattr_id_table_start);
6151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("\n");
6161f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
61734c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	return comp;
6181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherfailed_mount:
62034c07d5be0cabec0f7eac86d4b0b24392dcc07c0plougher	return NULL;
6211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
6221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
624e69aac119c4660c567d5159729b9875c3330e4bbplougherunsigned char *squashfs_readdir(int fd, int root_entries,
625e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int directory_start_block, int offset, int size,
62664e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher	unsigned int *last_directory_block, struct squashfs_super_block *sBlk,
627e69aac119c4660c567d5159729b9875c3330e4bbplougher	void (push_directory_entry)(char *, squashfs_inode, int, int))
6281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
629520e1a144c9a6c957754f93dc8830f884fe5669bplougher	struct squashfs_dir_header dirh;
6309b393553bbca1d7efc755a4b73e64407a526ef11plougher	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]
63146aefa984f924b2187e8f104fafed15899200237plougher		__attribute__ ((aligned));
6329b393553bbca1d7efc755a4b73e64407a526ef11plougher	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
6331f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	unsigned char *directory_table = NULL;
634df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher	int byte, bytes = 0, dir_count;
635e69aac119c4660c567d5159729b9875c3330e4bbplougher	long long start = sBlk->directory_table_start + directory_start_block,
636e69aac119c4660c567d5159729b9875c3330e4bbplougher		last_start_block = start;
6371f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	size += offset;
639e69aac119c4660c567d5159729b9875c3330e4bbplougher	directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) &
640e69aac119c4660c567d5159729b9875c3330e4bbplougher		~(SQUASHFS_METADATA_SIZE - 1));
641e69aac119c4660c567d5159729b9875c3330e4bbplougher	if(directory_table == NULL)
6429facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
6439facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
6441f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	while(bytes < size) {
645a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher		int expected = (size - bytes) >= SQUASHFS_METADATA_SIZE ?
646a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher			SQUASHFS_METADATA_SIZE : 0;
647a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher
648e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("squashfs_readdir: reading block 0x%llx, bytes read so "
649e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			"far %d\n", start, bytes);
650a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher
6511f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		last_start_block = start;
652a761c26cd25620f6dfaf7a452ee2ad6cfab9e1e3Phillip Lougher		byte = read_block(fd, start, &start, expected, directory_table + bytes);
653e69aac119c4660c567d5159729b9875c3330e4bbplougher		if(byte == 0) {
6542a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Failed to read directory\n");
6552a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
6561f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			free(directory_table);
6571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			return NULL;
6581f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
659df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher		bytes += byte;
6601f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
6611f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6621f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(!root_entries)
6631f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto all_done;
6641f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	bytes = offset;
6661f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher 	while(bytes < size) {
667690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher		SQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);
6681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6691f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		dir_count = dirh.count + 1;
670e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("squashfs_readdir: Read directory header @ byte position "
671e69aac119c4660c567d5159729b9875c3330e4bbplougher			"0x%x, 0x%x directory entries\n", bytes, dir_count);
6721f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		bytes += sizeof(dirh);
6731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		while(dir_count--) {
675690d91306e8b20400ae8c36fd558604189b70bdcPhillip Lougher			SQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);
6761f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			bytes += sizeof(*dire);
6771f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
678e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			memcpy(dire->name, directory_table + bytes,
679e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->size + 1);
6801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			dire->name[dire->size + 1] = '\0';
681e69aac119c4660c567d5159729b9875c3330e4bbplougher			TRACE("squashfs_readdir: pushing directory entry %s, "
682e69aac119c4660c567d5159729b9875c3330e4bbplougher				"inode %x:%x, type 0x%x\n", dire->name,
683e69aac119c4660c567d5159729b9875c3330e4bbplougher				dirh.start_block, dire->offset, dire->type);
684e69aac119c4660c567d5159729b9875c3330e4bbplougher			push_directory_entry(dire->name,
685e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				SQUASHFS_MKINODE(dirh.start_block,
686e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->offset), dirh.inode_number +
687e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher				dire->inode_number, dire->type);
6881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			bytes += dire->size + 1;
6891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
6901f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
6911f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6921f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherall_done:
693e69aac119c4660c567d5159729b9875c3330e4bbplougher	*last_directory_block = (unsigned int) last_start_block -
694e69aac119c4660c567d5159729b9875c3330e4bbplougher		sBlk->directory_table_start;
6951f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return directory_table;
6961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
6971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
6981f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
69964e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherunsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk)
7001b899fc316f7eba7a31da12dc0c9b69ada441059plougher{
7011b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids);
7021b899fc316f7eba7a31da12dc0c9b69ada441059plougher	long long index[indexes];
7031b899fc316f7eba7a31da12dc0c9b69ada441059plougher	int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids);
70461343797593e92ad2cf75b221398c138e1fee058plougher	unsigned int *id_table;
7051d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res, i;
7061b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7071b899fc316f7eba7a31da12dc0c9b69ada441059plougher	id_table = malloc(bytes);
7089facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(id_table == NULL)
7099facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
7101b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7111d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->id_table_start,
7123306cb2b54a60a32664617118336ac141e1471b6plougher		SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index);
7131d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
7149f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read id table index\n");
7159f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
7161d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(id_table);
7171d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return NULL;
7181d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
7191d065e9f3c6d22a629134837a55538fb8619cfb4plougher
72061343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);
7211b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7221b899fc316f7eba7a31da12dc0c9b69ada441059plougher	for(i = 0; i < indexes; i++) {
723197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
724197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher					bytes & (SQUASHFS_METADATA_SIZE - 1);
725197c9f6f6fde6e9aea7e269c936f26ff2f8466fePhillip Lougher		int length = read_block(fd, index[i], NULL, expected,
726e69aac119c4660c567d5159729b9875c3330e4bbplougher			((unsigned char *) id_table) +
727923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
728e69aac119c4660c567d5159729b9875c3330e4bbplougher		TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
729e69aac119c4660c567d5159729b9875c3330e4bbplougher			index[i], length);
730730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
731730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read id table block %d, from 0x%llx, "
732730ef508553ce562277b5d34fd272716e7ed6f13plougher				"length %d\n", i, index[i], length);
7332a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
734730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(id_table);
735730ef508553ce562277b5d34fd272716e7ed6f13plougher			return NULL;
736730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
7371b899fc316f7eba7a31da12dc0c9b69ada441059plougher	}
7381b899fc316f7eba7a31da12dc0c9b69ada441059plougher
73961343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);
7401b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7411b899fc316f7eba7a31da12dc0c9b69ada441059plougher	for(i = 0; i < sBlk->no_ids; i++) {
7421b899fc316f7eba7a31da12dc0c9b69ada441059plougher		TRACE("Adding id %d to id tables\n", id_table[i]);
7431b899fc316f7eba7a31da12dc0c9b69ada441059plougher		create_id(id_table[i]);
7441b899fc316f7eba7a31da12dc0c9b69ada441059plougher	}
7451b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7461b899fc316f7eba7a31da12dc0c9b69ada441059plougher	return id_table;
7471b899fc316f7eba7a31da12dc0c9b69ada441059plougher}
7481b899fc316f7eba7a31da12dc0c9b69ada441059plougher
7491b899fc316f7eba7a31da12dc0c9b69ada441059plougher
75064e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherint read_fragment_table(int fd, struct squashfs_super_block *sBlk,
7518ed84b96ca36da8147993935b951918359d8f20aplougher	struct squashfs_fragment_entry **fragment_table)
7521f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
753852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int res, i;
754852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int bytes = SQUASHFS_FRAGMENT_BYTES(sBlk->fragments);
755852db8287892bb34537830311de63c0cc5563783Phillip Lougher	int indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);
7562625a3d8f39b94c4841bd605361f4b575b0dc1a5plougher	long long fragment_table_index[indexes];
7571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
758e69aac119c4660c567d5159729b9875c3330e4bbplougher	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
759e69aac119c4660c567d5159729b9875c3330e4bbplougher		"from 0x%llx\n", sBlk->fragments, indexes,
760e69aac119c4660c567d5159729b9875c3330e4bbplougher		sBlk->fragment_table_start);
761852db8287892bb34537830311de63c0cc5563783Phillip Lougher
7621f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	if(sBlk->fragments == 0)
7631f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		return 1;
7641f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
765852db8287892bb34537830311de63c0cc5563783Phillip Lougher	*fragment_table = malloc(bytes);
7669facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(*fragment_table == NULL)
7679facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
7681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7691d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->fragment_table_start,
770e69aac119c4660c567d5159729b9875c3330e4bbplougher		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments),
7713306cb2b54a60a32664617118336ac141e1471b6plougher		fragment_table_index);
7721d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
7739f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read fragment table index\n");
7749f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
7751d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(*fragment_table);
7761d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
7771d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
7781d065e9f3c6d22a629134837a55538fb8619cfb4plougher
77961343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);
7801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
7811f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	for(i = 0; i < indexes; i++) {
782852db8287892bb34537830311de63c0cc5563783Phillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
783852db8287892bb34537830311de63c0cc5563783Phillip Lougher					bytes & (SQUASHFS_METADATA_SIZE - 1);
784852db8287892bb34537830311de63c0cc5563783Phillip Lougher		int length = read_block(fd, fragment_table_index[i], NULL,
785852db8287892bb34537830311de63c0cc5563783Phillip Lougher			expected, ((unsigned char *) *fragment_table) +
786923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
787e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
788e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			i, fragment_table_index[i], length);
789730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
790730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read fragment table block %d, from "
791730ef508553ce562277b5d34fd272716e7ed6f13plougher				"0x%llx, length %d\n", i,
792730ef508553ce562277b5d34fd272716e7ed6f13plougher				fragment_table_index[i], length);
7932a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
794730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(*fragment_table);
795730ef508553ce562277b5d34fd272716e7ed6f13plougher			return 0;
796730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
7971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
7981f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
79961343797593e92ad2cf75b221398c138e1fee058plougher	for(i = 0; i < sBlk->fragments; i++)
80061343797593e92ad2cf75b221398c138e1fee058plougher		SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]);
8011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8021f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return 1;
8031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
8041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8051f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
80664e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherint read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk,
807e69aac119c4660c567d5159729b9875c3330e4bbplougher	squashfs_inode **inode_lookup_table)
8080e45365737bf5283627e32253f2279c4d9fa32d0plougher{
8090e45365737bf5283627e32253f2279c4d9fa32d0plougher	int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes);
8100e45365737bf5283627e32253f2279c4d9fa32d0plougher	int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes);
8110e45365737bf5283627e32253f2279c4d9fa32d0plougher	long long index[indexes];
8121d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res, i;
8130e45365737bf5283627e32253f2279c4d9fa32d0plougher
8140e45365737bf5283627e32253f2279c4d9fa32d0plougher	if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK)
8150e45365737bf5283627e32253f2279c4d9fa32d0plougher		return 1;
8160e45365737bf5283627e32253f2279c4d9fa32d0plougher
817e69aac119c4660c567d5159729b9875c3330e4bbplougher	*inode_lookup_table = malloc(lookup_bytes);
8189facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher	if(*inode_lookup_table == NULL)
8199facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		MEM_ERROR();
8200e45365737bf5283627e32253f2279c4d9fa32d0plougher
8211d065e9f3c6d22a629134837a55538fb8619cfb4plougher	res = read_fs_bytes(fd, sBlk->lookup_table_start,
8223306cb2b54a60a32664617118336ac141e1471b6plougher		SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index);
8231d065e9f3c6d22a629134837a55538fb8619cfb4plougher	if(res == 0) {
8249f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Failed to read inode lookup table index\n");
8259f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		ERROR("Filesystem corrupted?\n");
8261d065e9f3c6d22a629134837a55538fb8619cfb4plougher		free(*inode_lookup_table);
8271d065e9f3c6d22a629134837a55538fb8619cfb4plougher		return 0;
8281d065e9f3c6d22a629134837a55538fb8619cfb4plougher	}
8291d065e9f3c6d22a629134837a55538fb8619cfb4plougher
83061343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_LONG_LONGS(index, indexes);
8310e45365737bf5283627e32253f2279c4d9fa32d0plougher
8320e45365737bf5283627e32253f2279c4d9fa32d0plougher	for(i = 0; i <  indexes; i++) {
833751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
834751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher				lookup_bytes & (SQUASHFS_METADATA_SIZE - 1);
835751e32fd169afa63e97a2d4d6f47aede3e98862aPhillip Lougher		int length = read_block(fd, index[i], NULL, expected,
836e69aac119c4660c567d5159729b9875c3330e4bbplougher			((unsigned char *) *inode_lookup_table) +
837923b301e304637fd5e587eb05a6f44558abae2bdplougher			(i * SQUASHFS_METADATA_SIZE));
838e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		TRACE("Read inode lookup table block %d, from 0x%llx, length "
839e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher			"%d\n", i, index[i], length);
840730ef508553ce562277b5d34fd272716e7ed6f13plougher		if(length == 0) {
841730ef508553ce562277b5d34fd272716e7ed6f13plougher			ERROR("Failed to read inode lookup table block %d, "
842730ef508553ce562277b5d34fd272716e7ed6f13plougher				"from 0x%llx, length %d\n", i, index[i],
843730ef508553ce562277b5d34fd272716e7ed6f13plougher				length);
8442a315732458c990f8e8185aac72d6c0a55350fffPhillip Lougher			ERROR("Filesystem corrupted?\n");
845730ef508553ce562277b5d34fd272716e7ed6f13plougher			free(*inode_lookup_table);
846730ef508553ce562277b5d34fd272716e7ed6f13plougher			return 0;
847730ef508553ce562277b5d34fd272716e7ed6f13plougher		}
8480e45365737bf5283627e32253f2279c4d9fa32d0plougher	}
8490e45365737bf5283627e32253f2279c4d9fa32d0plougher
85061343797593e92ad2cf75b221398c138e1fee058plougher	SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);
8510e45365737bf5283627e32253f2279c4d9fa32d0plougher
8520e45365737bf5283627e32253f2279c4d9fa32d0plougher	return 1;
8530e45365737bf5283627e32253f2279c4d9fa32d0plougher}
8540e45365737bf5283627e32253f2279c4d9fa32d0plougher
8550e45365737bf5283627e32253f2279c4d9fa32d0plougher
85664e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougherlong long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk,
857e69aac119c4660c567d5159729b9875c3330e4bbplougher	char **cinode_table, char **data_cache, char **cdirectory_table,
858e69aac119c4660c567d5159729b9875c3330e4bbplougher	char **directory_data_cache, unsigned int *last_directory_block,
859e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size,
860e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *root_inode_size, unsigned int *inode_dir_start_block,
861e69aac119c4660c567d5159729b9875c3330e4bbplougher	int *file_count, int *sym_count, int *dev_count, int *dir_count,
862e69aac119c4660c567d5159729b9875c3330e4bbplougher	int *fifo_count, int *sock_count, long long *uncompressed_file,
863e69aac119c4660c567d5159729b9875c3330e4bbplougher	unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
864e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int *inode_dir_inode_number,
865e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int *inode_dir_parent_inode,
866e69aac119c4660c567d5159729b9875c3330e4bbplougher	void (push_directory_entry)(char *, squashfs_inode, int, int),
8678ed84b96ca36da8147993935b951918359d8f20aplougher	struct squashfs_fragment_entry **fragment_table,
868e69aac119c4660c567d5159729b9875c3330e4bbplougher	squashfs_inode **inode_lookup_table)
8691f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher{
870096135f7430824033f597e47906a24d087f47a34Phillip Lougher	unsigned char *inode_table = NULL, *directory_table = NULL;
871e69aac119c4660c567d5159729b9875c3330e4bbplougher	long long start = sBlk->inode_table_start;
872e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	long long end = sBlk->directory_table_start;
873e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	long long root_inode_start = start +
8741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		SQUASHFS_INODE_BLK(sBlk->root_inode);
875e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher	unsigned int root_inode_offset =
876e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher		SQUASHFS_INODE_OFFSET(sBlk->root_inode);
8771a00ad1a4d97d54f83e41cc3d684de048bad3c10plougher	unsigned int root_inode_block;
8788973a12943b86e759a6391995271fa620d73483fplougher	union squashfs_inode_header inode;
879096135f7430824033f597e47906a24d087f47a34Phillip Lougher	unsigned int *id_table = NULL;
8801d065e9f3c6d22a629134837a55538fb8619cfb4plougher	int res;
8811f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	printf("Scanning existing filesystem...\n");
8831f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
884570f436c85a99435180a3ec9aeb1c94135ab0e77plougher	if(get_xattrs(fd, sBlk) == 0)
885570f436c85a99435180a3ec9aeb1c94135ab0e77plougher		goto error;
886570f436c85a99435180a3ec9aeb1c94135ab0e77plougher
8874c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher	if(read_fragment_table(fd, sBlk, fragment_table) == 0)
8881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto error;
8891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
8900e45365737bf5283627e32253f2279c4d9fa32d0plougher	if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0)
8910e45365737bf5283627e32253f2279c4d9fa32d0plougher		goto error;
8920e45365737bf5283627e32253f2279c4d9fa32d0plougher
8931b899fc316f7eba7a31da12dc0c9b69ada441059plougher	id_table = read_id_table(fd, sBlk);
8941b899fc316f7eba7a31da12dc0c9b69ada441059plougher	if(id_table == NULL)
8951b899fc316f7eba7a31da12dc0c9b69ada441059plougher		goto error;
8961b899fc316f7eba7a31da12dc0c9b69ada441059plougher
89796eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher	res = scan_inode_table(fd, start, end, root_inode_start,
89896eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		root_inode_offset, sBlk, &inode, &inode_table,
89996eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		&root_inode_block, root_inode_size, uncompressed_file,
90096eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		uncompressed_directory, file_count, sym_count, dev_count,
90196eedecdf4d075f5b860f8bf3eaab2a8ea2a805bplougher		dir_count, fifo_count, sock_count, id_table);
9021a734af8bd761a7737b56a55a9de04f3753500acPhillip Lougher	if(res == 0)
9031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		goto error;
9041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
9051f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	*uncompressed_inode = root_inode_block;
9061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
907e69aac119c4660c567d5159729b9875c3330e4bbplougher	if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
908e69aac119c4660c567d5159729b9875c3330e4bbplougher			inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
9091f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
9101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_start_block = inode.dir.start_block;
9111f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_offset = inode.dir.offset;
912058eae41952c33345bd0ef290aea8eef37f3ca92plougher			*inode_dir_file_size = inode.dir.file_size - 3;
913df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_inode_number = inode.dir.inode_number;
914df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_parent_inode = inode.dir.parent_inode;
9151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		} else {
9161f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_start_block = inode.ldir.start_block;
9171f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			*inode_dir_offset = inode.ldir.offset;
918058eae41952c33345bd0ef290aea8eef37f3ca92plougher			*inode_dir_file_size = inode.ldir.file_size - 3;
919df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_inode_number = inode.ldir.inode_number;
920df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher			*inode_dir_parent_inode = inode.ldir.parent_inode;
9211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		}
9221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
923e69aac119c4660c567d5159729b9875c3330e4bbplougher		directory_table = squashfs_readdir(fd, !root_name,
924e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_start_block, *inode_dir_offset,
925e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_file_size, last_directory_block, sBlk,
926e69aac119c4660c567d5159729b9875c3330e4bbplougher			push_directory_entry);
9274d7c0724196a5fce8fefa6ee923c79be7c94301bPhillip Lougher		if(directory_table == NULL)
9281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher			goto error;
9291f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
9301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		root_inode_start -= start;
931169d54f8cd07949d5708ff6ca7d48a06185ff604plougher		*cinode_table = malloc(root_inode_start);
9329facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*cinode_table == NULL)
9339facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9349facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
9351d065e9f3c6d22a629134837a55538fb8619cfb4plougher	       	res = read_fs_bytes(fd, start, root_inode_start, *cinode_table);
9369f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		if(res == 0) {
9379f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Failed to read inode table\n");
9389f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Filesystem corrupted?\n");
9391d065e9f3c6d22a629134837a55538fb8619cfb4plougher			goto error;
9409f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		}
9411f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
942e69aac119c4660c567d5159729b9875c3330e4bbplougher		*cdirectory_table = malloc(*last_directory_block);
9439facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*cdirectory_table == NULL)
9449facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9459facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
9461d065e9f3c6d22a629134837a55538fb8619cfb4plougher		res = read_fs_bytes(fd, sBlk->directory_table_start,
947e69aac119c4660c567d5159729b9875c3330e4bbplougher			*last_directory_block, *cdirectory_table);
9489f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		if(res == 0) {
9499f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher			ERROR("Failed to read directory table\n");
9509451938650abe45e8714660f420c0546ccb7a6aaPhillip Lougher			ERROR("Filesystem corrupted?\n");
9511d065e9f3c6d22a629134837a55538fb8619cfb4plougher			goto error;
9529f0a2c69377ffd7b2d066a4a06963d895727ae52Phillip Lougher		}
9531f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
954e69aac119c4660c567d5159729b9875c3330e4bbplougher		*data_cache = malloc(root_inode_offset + *root_inode_size);
9559facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*data_cache == NULL)
9569facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9579facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
958e69aac119c4660c567d5159729b9875c3330e4bbplougher		memcpy(*data_cache, inode_table + root_inode_block,
959e69aac119c4660c567d5159729b9875c3330e4bbplougher			root_inode_offset + *root_inode_size);
960e69aac119c4660c567d5159729b9875c3330e4bbplougher
961e69aac119c4660c567d5159729b9875c3330e4bbplougher		*directory_data_cache = malloc(*inode_dir_offset +
962e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_file_size);
9639facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher		if(*directory_data_cache == NULL)
9649facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher			MEM_ERROR();
9659facf01876801ce86eb06004959ab4aebb27fd39Phillip Lougher
966e69aac119c4660c567d5159729b9875c3330e4bbplougher		memcpy(*directory_data_cache, directory_table,
967e69aac119c4660c567d5159729b9875c3330e4bbplougher			*inode_dir_offset + *inode_dir_file_size);
9681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
969096135f7430824033f597e47906a24d087f47a34Phillip Lougher		free(id_table);
9701f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		free(inode_table);
9711f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		free(directory_table);
9721f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher		return sBlk->inode_table_start;
9731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	}
9741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
9751f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughererror:
976096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(id_table);
977096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(inode_table);
978096135f7430824033f597e47906a24d087f47a34Phillip Lougher	free(directory_table);
9791f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher	return 0;
9801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
981