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