unsquashfs.c revision b54566f5c433764830c29c83151691d0034de094
1443c15812032991c98b33b5424b17bcd55fe3575plougher/* 2443c15812032991c98b33b5424b17bcd55fe3575plougher * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. 3443c15812032991c98b33b5424b17bcd55fe3575plougher * 4769592935b09063a5493ebeb530c599753ece5d2plougher * Copyright (c) 2002, 2003, 2004, 2005, 2006 59b5bf8c73c0eaf4f1ba0461615f4ed0d405a30ccplougher * Phillip Lougher <phillip@lougher.org.uk> 6443c15812032991c98b33b5424b17bcd55fe3575plougher * 7443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is free software; you can redistribute it and/or 8443c15812032991c98b33b5424b17bcd55fe3575plougher * modify it under the terms of the GNU General Public License 9443c15812032991c98b33b5424b17bcd55fe3575plougher * as published by the Free Software Foundation; either version 2, 10443c15812032991c98b33b5424b17bcd55fe3575plougher * or (at your option) any later version. 11443c15812032991c98b33b5424b17bcd55fe3575plougher * 12443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is distributed in the hope that it will be useful, 13443c15812032991c98b33b5424b17bcd55fe3575plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 14443c15812032991c98b33b5424b17bcd55fe3575plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15443c15812032991c98b33b5424b17bcd55fe3575plougher * GNU General Public License for more details. 16443c15812032991c98b33b5424b17bcd55fe3575plougher * 17443c15812032991c98b33b5424b17bcd55fe3575plougher * You should have received a copy of the GNU General Public License 18443c15812032991c98b33b5424b17bcd55fe3575plougher * along with this program; if not, write to the Free Software 19443c15812032991c98b33b5424b17bcd55fe3575plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20443c15812032991c98b33b5424b17bcd55fe3575plougher * 21443c15812032991c98b33b5424b17bcd55fe3575plougher * unsquash.c 22443c15812032991c98b33b5424b17bcd55fe3575plougher */ 23443c15812032991c98b33b5424b17bcd55fe3575plougher 24443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRUE 1 25443c15812032991c98b33b5424b17bcd55fe3575plougher#define FALSE 0 26443c15812032991c98b33b5424b17bcd55fe3575plougher#include <stdio.h> 27443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/types.h> 28443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/stat.h> 29443c15812032991c98b33b5424b17bcd55fe3575plougher#include <fcntl.h> 30443c15812032991c98b33b5424b17bcd55fe3575plougher#include <errno.h> 31443c15812032991c98b33b5424b17bcd55fe3575plougher#include <string.h> 32443c15812032991c98b33b5424b17bcd55fe3575plougher#include <zlib.h> 33443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/mman.h> 34443c15812032991c98b33b5424b17bcd55fe3575plougher#include <utime.h> 35443c15812032991c98b33b5424b17bcd55fe3575plougher 36443c15812032991c98b33b5424b17bcd55fe3575plougher#ifndef linux 37443c15812032991c98b33b5424b17bcd55fe3575plougher#define __BYTE_ORDER BYTE_ORDER 38443c15812032991c98b33b5424b17bcd55fe3575plougher#define __BIG_ENDIAN BIG_ENDIAN 39443c15812032991c98b33b5424b17bcd55fe3575plougher#define __LITTLE_ENDIAN LITTLE_ENDIAN 40443c15812032991c98b33b5424b17bcd55fe3575plougher#else 41443c15812032991c98b33b5424b17bcd55fe3575plougher#include <endian.h> 42443c15812032991c98b33b5424b17bcd55fe3575plougher#endif 43443c15812032991c98b33b5424b17bcd55fe3575plougher 44443c15812032991c98b33b5424b17bcd55fe3575plougher#include <squashfs_fs.h> 45443c15812032991c98b33b5424b17bcd55fe3575plougher#include "read_fs.h" 46443c15812032991c98b33b5424b17bcd55fe3575plougher#include "global.h" 47443c15812032991c98b33b5424b17bcd55fe3575plougher 48443c15812032991c98b33b5424b17bcd55fe3575plougher#include <stdlib.h> 49443c15812032991c98b33b5424b17bcd55fe3575plougher 50443c15812032991c98b33b5424b17bcd55fe3575plougher#ifdef SQUASHFS_TRACE 51443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRACE(s, args...) do { \ 52443c15812032991c98b33b5424b17bcd55fe3575plougher printf("mksquashfs: "s, ## args); \ 53443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 54443c15812032991c98b33b5424b17bcd55fe3575plougher#else 55443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRACE(s, args...) 56443c15812032991c98b33b5424b17bcd55fe3575plougher#endif 57443c15812032991c98b33b5424b17bcd55fe3575plougher 58443c15812032991c98b33b5424b17bcd55fe3575plougher#define ERROR(s, args...) do { \ 59443c15812032991c98b33b5424b17bcd55fe3575plougher fprintf(stderr, s, ## args); \ 60443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 61443c15812032991c98b33b5424b17bcd55fe3575plougher 62443c15812032991c98b33b5424b17bcd55fe3575plougher#define EXIT_UNSQUASH(s, args...) do { \ 63443c15812032991c98b33b5424b17bcd55fe3575plougher fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ 64443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 65443c15812032991c98b33b5424b17bcd55fe3575plougher 66443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry { 67443c15812032991c98b33b5424b17bcd55fe3575plougher int start; 68443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes; 69443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *next; 70443c15812032991c98b33b5424b17bcd55fe3575plougher}; 71443c15812032991c98b33b5424b17bcd55fe3575plougher 72443c15812032991c98b33b5424b17bcd55fe3575plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; 73443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 74443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 75443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 76443c15812032991c98b33b5424b17bcd55fe3575ploughersquashfs_fragment_entry *fragment_table; 77443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 78443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 79443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 80443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 81443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 82443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 83443c15812032991c98b33b5424b17bcd55fe3575plougherint lsonly = FALSE, info = FALSE; 84443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 85443c15812032991c98b33b5424b17bcd55fe3575plougher 86443c15812032991c98b33b5424b17bcd55fe3575plougher#define CALCULATE_HASH(start) (start & 0xffff) 87443c15812032991c98b33b5424b17bcd55fe3575plougher 88443c15812032991c98b33b5424b17bcd55fe3575plougherint add_entry(struct hash_table_entry *hash_table[], int start, int bytes) 89443c15812032991c98b33b5424b17bcd55fe3575plougher{ 90443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 91443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 92443c15812032991c98b33b5424b17bcd55fe3575plougher 93443c15812032991c98b33b5424b17bcd55fe3575plougher if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { 94443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("add_hash: out of memory in malloc\n"); 95443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 96443c15812032991c98b33b5424b17bcd55fe3575plougher } 97443c15812032991c98b33b5424b17bcd55fe3575plougher 98443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 99443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 100443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 101443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 102443c15812032991c98b33b5424b17bcd55fe3575plougher 103443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 104443c15812032991c98b33b5424b17bcd55fe3575plougher} 105443c15812032991c98b33b5424b17bcd55fe3575plougher 106443c15812032991c98b33b5424b17bcd55fe3575plougher 107443c15812032991c98b33b5424b17bcd55fe3575plougherint lookup_entry(struct hash_table_entry *hash_table[], int start) 108443c15812032991c98b33b5424b17bcd55fe3575plougher{ 109443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 110443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 111443c15812032991c98b33b5424b17bcd55fe3575plougher 112443c15812032991c98b33b5424b17bcd55fe3575plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) 113443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 114443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 115443c15812032991c98b33b5424b17bcd55fe3575plougher 116443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 117443c15812032991c98b33b5424b17bcd55fe3575plougher} 118443c15812032991c98b33b5424b17bcd55fe3575plougher 119443c15812032991c98b33b5424b17bcd55fe3575plougher 120443c15812032991c98b33b5424b17bcd55fe3575plougherint read_bytes(long long byte, int bytes, char *buff) 121443c15812032991c98b33b5424b17bcd55fe3575plougher{ 122443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 123443c15812032991c98b33b5424b17bcd55fe3575plougher 124fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); 125fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 126443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 127443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Lseek failed because %s\b", strerror(errno)); 128443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 129443c15812032991c98b33b5424b17bcd55fe3575plougher } 130443c15812032991c98b33b5424b17bcd55fe3575plougher 131443c15812032991c98b33b5424b17bcd55fe3575plougher if(read(fd, buff, bytes) == -1) { 132443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Read on destination failed because %s\n", strerror(errno)); 133443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 134443c15812032991c98b33b5424b17bcd55fe3575plougher } 135443c15812032991c98b33b5424b17bcd55fe3575plougher 136443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 137443c15812032991c98b33b5424b17bcd55fe3575plougher} 138443c15812032991c98b33b5424b17bcd55fe3575plougher 139443c15812032991c98b33b5424b17bcd55fe3575plougher 140443c15812032991c98b33b5424b17bcd55fe3575plougherint read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk) 141443c15812032991c98b33b5424b17bcd55fe3575plougher{ 142443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 143443c15812032991c98b33b5424b17bcd55fe3575plougher int offset = 2; 144443c15812032991c98b33b5424b17bcd55fe3575plougher 145443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 146443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, block) == FALSE) 147fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 148443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[1] = block[0]; 149443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[0] = block[1]; 150443c15812032991c98b33b5424b17bcd55fe3575plougher } else 151443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, (char *)&c_byte) == FALSE) 152fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 153fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 154fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); 155443c15812032991c98b33b5424b17bcd55fe3575plougher 156443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_CHECK_DATA(sBlk->flags)) 157443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 158443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED(c_byte)) { 159443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[SQUASHFS_METADATA_SIZE]; 160443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 161443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = SQUASHFS_METADATA_SIZE; 162443c15812032991c98b33b5424b17bcd55fe3575plougher 163443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 164443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, buffer) == FALSE) 165fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 166443c15812032991c98b33b5424b17bcd55fe3575plougher 167443c15812032991c98b33b5424b17bcd55fe3575plougher if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { 168443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 169443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough memory\n"); 170443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 171443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough room in output buffer\n"); 172443c15812032991c98b33b5424b17bcd55fe3575plougher else 173443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, unknown error %d\n", res); 174fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 175443c15812032991c98b33b5424b17bcd55fe3575plougher } 176443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 177443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 178443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 179443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 180443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 181443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, block) == FALSE) 182fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 183443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 184443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 185443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 186443c15812032991c98b33b5424b17bcd55fe3575plougher } 187fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 188fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 189fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 190443c15812032991c98b33b5424b17bcd55fe3575plougher} 191443c15812032991c98b33b5424b17bcd55fe3575plougher 192443c15812032991c98b33b5424b17bcd55fe3575plougher 193443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 194443c15812032991c98b33b5424b17bcd55fe3575plougher{ 195443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 196443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = block_size; 197443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 198443c15812032991c98b33b5424b17bcd55fe3575plougher 199fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); 200fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 201443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 202443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, data) == FALSE) 203443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 204443c15812032991c98b33b5424b17bcd55fe3575plougher 205443c15812032991c98b33b5424b17bcd55fe3575plougher if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { 206443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 207443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough memory\n"); 208443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 209443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough room in output buffer\n"); 210443c15812032991c98b33b5424b17bcd55fe3575plougher else 211443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, unknown error %d\n", res); 212443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 213443c15812032991c98b33b5424b17bcd55fe3575plougher } 214443c15812032991c98b33b5424b17bcd55fe3575plougher 215443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 216443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 217443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, block) == FALSE) 218443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 219443c15812032991c98b33b5424b17bcd55fe3575plougher 220443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 221443c15812032991c98b33b5424b17bcd55fe3575plougher } 222443c15812032991c98b33b5424b17bcd55fe3575plougher} 223443c15812032991c98b33b5424b17bcd55fe3575plougher 224443c15812032991c98b33b5424b17bcd55fe3575plougher 225443c15812032991c98b33b5424b17bcd55fe3575ploughervoid uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk) 226443c15812032991c98b33b5424b17bcd55fe3575plougher{ 227443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 228443c15812032991c98b33b5424b17bcd55fe3575plougher 229443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 230443c15812032991c98b33b5424b17bcd55fe3575plougher if((size - bytes < SQUASHFS_METADATA_SIZE) && 231443c15812032991c98b33b5424b17bcd55fe3575plougher ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) 232443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); 233443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_inode_table: reading block 0x%llx\n", start); 234443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 235443c15812032991c98b33b5424b17bcd55fe3575plougher if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) { 236443c15812032991c98b33b5424b17bcd55fe3575plougher free(inode_table); 237443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); 238443c15812032991c98b33b5424b17bcd55fe3575plougher } 239443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 240443c15812032991c98b33b5424b17bcd55fe3575plougher } 241443c15812032991c98b33b5424b17bcd55fe3575plougher} 242443c15812032991c98b33b5424b17bcd55fe3575plougher 243443c15812032991c98b33b5424b17bcd55fe3575plougher 244443c15812032991c98b33b5424b17bcd55fe3575plougherint set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, 245443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int mtime, unsigned int set_mode) 246443c15812032991c98b33b5424b17bcd55fe3575plougher{ 247443c15812032991c98b33b5424b17bcd55fe3575plougher struct utimbuf times = { (time_t) mtime, (time_t) mtime }; 248443c15812032991c98b33b5424b17bcd55fe3575plougher 249443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 250443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); 251443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 252443c15812032991c98b33b5424b17bcd55fe3575plougher } 253443c15812032991c98b33b5424b17bcd55fe3575plougher 254443c15812032991c98b33b5424b17bcd55fe3575plougher if(set_mode && chmod(pathname, (mode_t) mode) == -1) { 255443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); 256443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 257443c15812032991c98b33b5424b17bcd55fe3575plougher } 258443c15812032991c98b33b5424b17bcd55fe3575plougher 259443c15812032991c98b33b5424b17bcd55fe3575plougher if(geteuid() == 0) { 260443c15812032991c98b33b5424b17bcd55fe3575plougher uid_t uid_value = (uid_t) uid_table[uid]; 261443c15812032991c98b33b5424b17bcd55fe3575plougher uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; 262443c15812032991c98b33b5424b17bcd55fe3575plougher 263443c15812032991c98b33b5424b17bcd55fe3575plougher if(chown(pathname, uid_value, guid_value) == -1) { 264443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); 265443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 266443c15812032991c98b33b5424b17bcd55fe3575plougher } 267443c15812032991c98b33b5424b17bcd55fe3575plougher } 268443c15812032991c98b33b5424b17bcd55fe3575plougher 269443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 270443c15812032991c98b33b5424b17bcd55fe3575plougher} 271443c15812032991c98b33b5424b17bcd55fe3575plougher 272443c15812032991c98b33b5424b17bcd55fe3575plougher 273443c15812032991c98b33b5424b17bcd55fe3575ploughervoid read_uids_guids(squashfs_super_block *sBlk) 274443c15812032991c98b33b5424b17bcd55fe3575plougher{ 275443c15812032991c98b33b5424b17bcd55fe3575plougher if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL) 276443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); 277443c15812032991c98b33b5424b17bcd55fe3575plougher 278443c15812032991c98b33b5424b17bcd55fe3575plougher guid_table = uid_table + sBlk->no_uids; 279443c15812032991c98b33b5424b17bcd55fe3575plougher 280fc9aa5457df027969c6616cdf93fc1945ad7688eplougher if(swap) { 281fc9aa5457df027969c6616cdf93fc1945ad7688eplougher unsigned int suid_table[sBlk->no_uids + sBlk->no_guids]; 282fc9aa5457df027969c6616cdf93fc1945ad7688eplougher 283fc9aa5457df027969c6616cdf93fc1945ad7688eplougher if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) suid_table) == 284fc9aa5457df027969c6616cdf93fc1945ad7688eplougher FALSE) 285fc9aa5457df027969c6616cdf93fc1945ad7688eplougher EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); 286fc9aa5457df027969c6616cdf93fc1945ad7688eplougher SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk->no_uids + sBlk->no_guids); 287fc9aa5457df027969c6616cdf93fc1945ad7688eplougher } else 288fc9aa5457df027969c6616cdf93fc1945ad7688eplougher if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) == 289443c15812032991c98b33b5424b17bcd55fe3575plougher FALSE) 290fc9aa5457df027969c6616cdf93fc1945ad7688eplougher EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); 291443c15812032991c98b33b5424b17bcd55fe3575plougher} 292443c15812032991c98b33b5424b17bcd55fe3575plougher 293443c15812032991c98b33b5424b17bcd55fe3575plougher 294443c15812032991c98b33b5424b17bcd55fe3575ploughervoid read_fragment_table(squashfs_super_block *sBlk) 295443c15812032991c98b33b5424b17bcd55fe3575plougher{ 296443c15812032991c98b33b5424b17bcd55fe3575plougher int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); 297443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_index fragment_table_index[indexes]; 298443c15812032991c98b33b5424b17bcd55fe3575plougher 299fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); 300443c15812032991c98b33b5424b17bcd55fe3575plougher if(sBlk->fragments == 0) 301443c15812032991c98b33b5424b17bcd55fe3575plougher return; 302443c15812032991c98b33b5424b17bcd55fe3575plougher 303443c15812032991c98b33b5424b17bcd55fe3575plougher if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) 304443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); 305443c15812032991c98b33b5424b17bcd55fe3575plougher 306443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 307443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_index sfragment_table_index[indexes]; 308443c15812032991c98b33b5424b17bcd55fe3575plougher 309443c15812032991c98b33b5424b17bcd55fe3575plougher read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); 310443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); 311443c15812032991c98b33b5424b17bcd55fe3575plougher } else 312443c15812032991c98b33b5424b17bcd55fe3575plougher read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); 313443c15812032991c98b33b5424b17bcd55fe3575plougher 314443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 0; i < indexes; i++) { 315443c15812032991c98b33b5424b17bcd55fe3575plougher int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); 316fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); 317443c15812032991c98b33b5424b17bcd55fe3575plougher } 318443c15812032991c98b33b5424b17bcd55fe3575plougher 319443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 320443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_entry sfragment; 321443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 0; i < sBlk->fragments; i++) { 322443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); 323443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); 324443c15812032991c98b33b5424b17bcd55fe3575plougher } 325443c15812032991c98b33b5424b17bcd55fe3575plougher } 326443c15812032991c98b33b5424b17bcd55fe3575plougher} 327443c15812032991c98b33b5424b17bcd55fe3575plougher 328443c15812032991c98b33b5424b17bcd55fe3575plougher 329443c15812032991c98b33b5424b17bcd55fe3575plougherchar *read_fragment(unsigned int fragment) 330443c15812032991c98b33b5424b17bcd55fe3575plougher{ 331fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_fragment: reading fragment %d\n", fragment); 332fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 333443c15812032991c98b33b5424b17bcd55fe3575plougher if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { 334443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; 335443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { 336443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("read_fragment: failed to read fragment %d\n", fragment); 337443c15812032991c98b33b5424b17bcd55fe3575plougher cached_frag = SQUASHFS_INVALID_FRAG; 338443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 339443c15812032991c98b33b5424b17bcd55fe3575plougher } 340443c15812032991c98b33b5424b17bcd55fe3575plougher cached_frag = fragment; 341443c15812032991c98b33b5424b17bcd55fe3575plougher } 342443c15812032991c98b33b5424b17bcd55fe3575plougher 343443c15812032991c98b33b5424b17bcd55fe3575plougher return fragment_data; 344443c15812032991c98b33b5424b17bcd55fe3575plougher} 345443c15812032991c98b33b5424b17bcd55fe3575plougher 346443c15812032991c98b33b5424b17bcd55fe3575plougher 347443c15812032991c98b33b5424b17bcd55fe3575plougherint write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, 348443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int blocks, long long start, char *block_ptr, unsigned int mode) 349443c15812032991c98b33b5424b17bcd55fe3575plougher{ 350f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int file_fd, bytes, i; 351f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 352443c15812032991c98b33b5424b17bcd55fe3575plougher 353443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("write_file: regular file, blocks %d\n", blocks); 354443c15812032991c98b33b5424b17bcd55fe3575plougher 355f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { 356f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher ERROR("write_file: unable to malloc block list\n"); 357f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher return FALSE; 358f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher } 359f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher 360443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 361443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int sblock_list[blocks]; 362443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); 363443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); 364443c15812032991c98b33b5424b17bcd55fe3575plougher } else 365443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); 366443c15812032991c98b33b5424b17bcd55fe3575plougher 367443c15812032991c98b33b5424b17bcd55fe3575plougher if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) { 368443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("write_file: failed to create file %s, because %s\n", pathname, 369443c15812032991c98b33b5424b17bcd55fe3575plougher strerror(errno)); 370f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher free(block_list); 371443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 372443c15812032991c98b33b5424b17bcd55fe3575plougher } 373443c15812032991c98b33b5424b17bcd55fe3575plougher 374443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 0; i < blocks; i++) { 375443c15812032991c98b33b5424b17bcd55fe3575plougher if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { 376fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("write_file: failed to read data block 0x%llx\n", start); 377443c15812032991c98b33b5424b17bcd55fe3575plougher goto failure; 378443c15812032991c98b33b5424b17bcd55fe3575plougher } 379443c15812032991c98b33b5424b17bcd55fe3575plougher 380443c15812032991c98b33b5424b17bcd55fe3575plougher if(write(file_fd, file_data, bytes) < bytes) { 381fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("write_file: failed to write data block 0x%llx\n", start); 382443c15812032991c98b33b5424b17bcd55fe3575plougher goto failure; 383443c15812032991c98b33b5424b17bcd55fe3575plougher } 384443c15812032991c98b33b5424b17bcd55fe3575plougher 385443c15812032991c98b33b5424b17bcd55fe3575plougher start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 386443c15812032991c98b33b5424b17bcd55fe3575plougher } 387443c15812032991c98b33b5424b17bcd55fe3575plougher 388443c15812032991c98b33b5424b17bcd55fe3575plougher if(frag_bytes != 0) { 389443c15812032991c98b33b5424b17bcd55fe3575plougher char *fragment_data = read_fragment(fragment); 390443c15812032991c98b33b5424b17bcd55fe3575plougher 391443c15812032991c98b33b5424b17bcd55fe3575plougher if(fragment_data == NULL) 392443c15812032991c98b33b5424b17bcd55fe3575plougher goto failure; 393443c15812032991c98b33b5424b17bcd55fe3575plougher 394443c15812032991c98b33b5424b17bcd55fe3575plougher if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { 395fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("write_file: failed to write fragment %d\n", fragment); 396443c15812032991c98b33b5424b17bcd55fe3575plougher goto failure; 397443c15812032991c98b33b5424b17bcd55fe3575plougher } 398443c15812032991c98b33b5424b17bcd55fe3575plougher } 399443c15812032991c98b33b5424b17bcd55fe3575plougher 400443c15812032991c98b33b5424b17bcd55fe3575plougher close(file_fd); 401443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 402443c15812032991c98b33b5424b17bcd55fe3575plougher 403443c15812032991c98b33b5424b17bcd55fe3575plougherfailure: 404443c15812032991c98b33b5424b17bcd55fe3575plougher close(file_fd); 405f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher free(block_list); 406443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 407443c15812032991c98b33b5424b17bcd55fe3575plougher} 408443c15812032991c98b33b5424b17bcd55fe3575plougher 409443c15812032991c98b33b5424b17bcd55fe3575plougher 410443c15812032991c98b33b5424b17bcd55fe3575plougherint create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) 411443c15812032991c98b33b5424b17bcd55fe3575plougher{ 412443c15812032991c98b33b5424b17bcd55fe3575plougher long long start = sBlk->inode_table_start + start_block; 413443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_inode_header header; 414443c15812032991c98b33b5424b17bcd55fe3575plougher char *block_ptr; 415443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = lookup_entry(inode_table_hash, start), file_fd; 416443c15812032991c98b33b5424b17bcd55fe3575plougher 417fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); 418443c15812032991c98b33b5424b17bcd55fe3575plougher 419443c15812032991c98b33b5424b17bcd55fe3575plougher if(bytes == -1) { 420443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: inode block 0x%llx out of range!\n", start); 421443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 422443c15812032991c98b33b5424b17bcd55fe3575plougher } 423443c15812032991c98b33b5424b17bcd55fe3575plougher block_ptr = inode_table + bytes + offset; 424443c15812032991c98b33b5424b17bcd55fe3575plougher 425443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 426443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_base_inode_header sinode; 427443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinode, block_ptr, sizeof(header.base)); 428443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); 429443c15812032991c98b33b5424b17bcd55fe3575plougher } else 430443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&header.base, block_ptr, sizeof(header.base)); 431443c15812032991c98b33b5424b17bcd55fe3575plougher 432443c15812032991c98b33b5424b17bcd55fe3575plougher if(created_inode[header.base.inode_number - 1]) { 433443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 434443c15812032991c98b33b5424b17bcd55fe3575plougher if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { 435443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); 436443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 437443c15812032991c98b33b5424b17bcd55fe3575plougher } 438443c15812032991c98b33b5424b17bcd55fe3575plougher 439443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 440443c15812032991c98b33b5424b17bcd55fe3575plougher } 441443c15812032991c98b33b5424b17bcd55fe3575plougher 442443c15812032991c98b33b5424b17bcd55fe3575plougher switch(header.base.inode_type) { 443443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FILE_TYPE: { 444443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int frag_bytes; 445443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int blocks; 446443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int offset; 447443c15812032991c98b33b5424b17bcd55fe3575plougher long long start; 448443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_reg_inode_header *inode = &header.reg; 449443c15812032991c98b33b5424b17bcd55fe3575plougher 450443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 451443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_reg_inode_header sinode; 452443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinode, block_ptr, sizeof(sinode)); 453443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); 454443c15812032991c98b33b5424b17bcd55fe3575plougher } else 455443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(inode, block_ptr, sizeof(*inode)); 456443c15812032991c98b33b5424b17bcd55fe3575plougher 457443c15812032991c98b33b5424b17bcd55fe3575plougher frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; 458443c15812032991c98b33b5424b17bcd55fe3575plougher offset = inode->offset; 459443c15812032991c98b33b5424b17bcd55fe3575plougher blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size 460443c15812032991c98b33b5424b17bcd55fe3575plougher + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> 461443c15812032991c98b33b5424b17bcd55fe3575plougher sBlk->block_log; 462443c15812032991c98b33b5424b17bcd55fe3575plougher start = inode->start_block; 463443c15812032991c98b33b5424b17bcd55fe3575plougher 464443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); 465443c15812032991c98b33b5424b17bcd55fe3575plougher 466443c15812032991c98b33b5424b17bcd55fe3575plougher if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, 467443c15812032991c98b33b5424b17bcd55fe3575plougher block_ptr + sizeof(*inode), inode->mode)) { 468443c15812032991c98b33b5424b17bcd55fe3575plougher set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); 469443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 470443c15812032991c98b33b5424b17bcd55fe3575plougher } 471443c15812032991c98b33b5424b17bcd55fe3575plougher break; 472443c15812032991c98b33b5424b17bcd55fe3575plougher } 473443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_LREG_TYPE: { 474443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int frag_bytes; 475443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int blocks; 476443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int offset; 477443c15812032991c98b33b5424b17bcd55fe3575plougher long long start; 478443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_lreg_inode_header *inode = &header.lreg; 479443c15812032991c98b33b5424b17bcd55fe3575plougher 480443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 481443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_lreg_inode_header sinode; 482443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinode, block_ptr, sizeof(sinode)); 483443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); 484443c15812032991c98b33b5424b17bcd55fe3575plougher } else 485443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(inode, block_ptr, sizeof(*inode)); 486443c15812032991c98b33b5424b17bcd55fe3575plougher 487443c15812032991c98b33b5424b17bcd55fe3575plougher frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; 488443c15812032991c98b33b5424b17bcd55fe3575plougher offset = inode->offset; 489443c15812032991c98b33b5424b17bcd55fe3575plougher blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size 490443c15812032991c98b33b5424b17bcd55fe3575plougher + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> 491443c15812032991c98b33b5424b17bcd55fe3575plougher sBlk->block_log; 492443c15812032991c98b33b5424b17bcd55fe3575plougher start = inode->start_block; 493443c15812032991c98b33b5424b17bcd55fe3575plougher 494443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); 495443c15812032991c98b33b5424b17bcd55fe3575plougher 496443c15812032991c98b33b5424b17bcd55fe3575plougher if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, 497443c15812032991c98b33b5424b17bcd55fe3575plougher block_ptr + sizeof(*inode), inode->mode)) { 498443c15812032991c98b33b5424b17bcd55fe3575plougher set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); 499443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 500443c15812032991c98b33b5424b17bcd55fe3575plougher } 501443c15812032991c98b33b5424b17bcd55fe3575plougher break; 502443c15812032991c98b33b5424b17bcd55fe3575plougher } 503443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SYMLINK_TYPE: { 504443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_symlink_inode_header *inodep = &header.symlink; 505443c15812032991c98b33b5424b17bcd55fe3575plougher char name[65536]; 506443c15812032991c98b33b5424b17bcd55fe3575plougher 507443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 508443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_symlink_inode_header sinodep; 509443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 510443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); 511443c15812032991c98b33b5424b17bcd55fe3575plougher } else 512443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(inodep, block_ptr, sizeof(*inodep)); 513443c15812032991c98b33b5424b17bcd55fe3575plougher 514443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); 515443c15812032991c98b33b5424b17bcd55fe3575plougher 516443c15812032991c98b33b5424b17bcd55fe3575plougher strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); 517443c15812032991c98b33b5424b17bcd55fe3575plougher name[inodep->symlink_size] = '\0'; 518443c15812032991c98b33b5424b17bcd55fe3575plougher 519443c15812032991c98b33b5424b17bcd55fe3575plougher if(symlink(name, pathname) == -1) { 520443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, 521443c15812032991c98b33b5424b17bcd55fe3575plougher strerror(errno)); 522443c15812032991c98b33b5424b17bcd55fe3575plougher break; 523443c15812032991c98b33b5424b17bcd55fe3575plougher } 524443c15812032991c98b33b5424b17bcd55fe3575plougher 525443c15812032991c98b33b5424b17bcd55fe3575plougher if(geteuid() == 0) { 526443c15812032991c98b33b5424b17bcd55fe3575plougher uid_t uid_value = (uid_t) uid_table[inodep->uid]; 527443c15812032991c98b33b5424b17bcd55fe3575plougher uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; 528443c15812032991c98b33b5424b17bcd55fe3575plougher 529443c15812032991c98b33b5424b17bcd55fe3575plougher if(lchown(pathname, uid_value, guid_value) == -1) 530443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); 531443c15812032991c98b33b5424b17bcd55fe3575plougher } 532443c15812032991c98b33b5424b17bcd55fe3575plougher 533443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 534443c15812032991c98b33b5424b17bcd55fe3575plougher break; 535443c15812032991c98b33b5424b17bcd55fe3575plougher } 536443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 537443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_CHRDEV_TYPE: { 538443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dev_inode_header *inodep = &header.dev; 539443c15812032991c98b33b5424b17bcd55fe3575plougher 540443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 541443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dev_inode_header sinodep; 542443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 543443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); 544443c15812032991c98b33b5424b17bcd55fe3575plougher } else 545443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(inodep, block_ptr, sizeof(*inodep)); 546443c15812032991c98b33b5424b17bcd55fe3575plougher 547443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); 548443c15812032991c98b33b5424b17bcd55fe3575plougher 549443c15812032991c98b33b5424b17bcd55fe3575plougher if(geteuid() == 0) { 550443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, 551443c15812032991c98b33b5424b17bcd55fe3575plougher makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) 552443c15812032991c98b33b5424b17bcd55fe3575plougher == -1) { 553443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create %s device %s, because %s\n", 554443c15812032991c98b33b5424b17bcd55fe3575plougher inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", 555443c15812032991c98b33b5424b17bcd55fe3575plougher pathname, strerror(errno)); 556443c15812032991c98b33b5424b17bcd55fe3575plougher break; 557443c15812032991c98b33b5424b17bcd55fe3575plougher } 558443c15812032991c98b33b5424b17bcd55fe3575plougher set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); 559443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 560443c15812032991c98b33b5424b17bcd55fe3575plougher } else 561443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", 562443c15812032991c98b33b5424b17bcd55fe3575plougher inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", 563443c15812032991c98b33b5424b17bcd55fe3575plougher pathname, strerror(errno)); 564443c15812032991c98b33b5424b17bcd55fe3575plougher break; 565fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher } 566443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 567443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 568443c15812032991c98b33b5424b17bcd55fe3575plougher 569443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 570443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create fifo %s, because %s\n", 571443c15812032991c98b33b5424b17bcd55fe3575plougher pathname, strerror(errno)); 572443c15812032991c98b33b5424b17bcd55fe3575plougher break; 573443c15812032991c98b33b5424b17bcd55fe3575plougher } 574443c15812032991c98b33b5424b17bcd55fe3575plougher set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, 575443c15812032991c98b33b5424b17bcd55fe3575plougher header.base.mtime, TRUE); 576443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 577443c15812032991c98b33b5424b17bcd55fe3575plougher break; 578443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 579443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 580443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 581443c15812032991c98b33b5424b17bcd55fe3575plougher break; 582443c15812032991c98b33b5424b17bcd55fe3575plougher default: 583443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); 584443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 585443c15812032991c98b33b5424b17bcd55fe3575plougher } 586fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 587443c15812032991c98b33b5424b17bcd55fe3575plougher created_inode[header.base.inode_number - 1] = strdup(pathname); 588443c15812032991c98b33b5424b17bcd55fe3575plougher 589443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 590443c15812032991c98b33b5424b17bcd55fe3575plougher} 591443c15812032991c98b33b5424b17bcd55fe3575plougher 592443c15812032991c98b33b5424b17bcd55fe3575plougher 593443c15812032991c98b33b5424b17bcd55fe3575ploughervoid uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk) 594443c15812032991c98b33b5424b17bcd55fe3575plougher{ 595443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 596443c15812032991c98b33b5424b17bcd55fe3575plougher 597443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 598443c15812032991c98b33b5424b17bcd55fe3575plougher if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) 599443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); 600443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_directory_table: reading block 0x%llx\n", start); 601443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 602443c15812032991c98b33b5424b17bcd55fe3575plougher if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0) 603443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); 604443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 605443c15812032991c98b33b5424b17bcd55fe3575plougher } 606443c15812032991c98b33b5424b17bcd55fe3575plougher} 607443c15812032991c98b33b5424b17bcd55fe3575plougher 608443c15812032991c98b33b5424b17bcd55fe3575plougher 609443c15812032991c98b33b5424b17bcd55fe3575plougher#define DIR_ENT_SIZE 16 610443c15812032991c98b33b5424b17bcd55fe3575plougher 611443c15812032991c98b33b5424b17bcd55fe3575plougherstruct dir_ent { 612443c15812032991c98b33b5424b17bcd55fe3575plougher char name[SQUASHFS_NAME_LEN + 1]; 613443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int start_block; 614443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int offset; 615443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 616443c15812032991c98b33b5424b17bcd55fe3575plougher}; 617443c15812032991c98b33b5424b17bcd55fe3575plougher 618443c15812032991c98b33b5424b17bcd55fe3575plougherstruct dir { 619443c15812032991c98b33b5424b17bcd55fe3575plougher int dir_count; 620443c15812032991c98b33b5424b17bcd55fe3575plougher int cur_entry; 621443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int mode; 622443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int uid; 623443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int guid; 624443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int mtime; 625443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir_ent *dirs; 626443c15812032991c98b33b5424b17bcd55fe3575plougher}; 627443c15812032991c98b33b5424b17bcd55fe3575plougher 628443c15812032991c98b33b5424b17bcd55fe3575plougher 629443c15812032991c98b33b5424b17bcd55fe3575plougherstruct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk) 630443c15812032991c98b33b5424b17bcd55fe3575plougher{ 631443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_header dirh; 632443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; 633443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; 634443c15812032991c98b33b5424b17bcd55fe3575plougher long long start = sBlk->inode_table_start + block_start; 635443c15812032991c98b33b5424b17bcd55fe3575plougher char *block_ptr; 636443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = lookup_entry(inode_table_hash, start); 637443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_inode_header header; 638443c15812032991c98b33b5424b17bcd55fe3575plougher int dir_count, size; 639443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir_ent *new_dir; 640443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir *dir; 641443c15812032991c98b33b5424b17bcd55fe3575plougher 642fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); 643443c15812032991c98b33b5424b17bcd55fe3575plougher 644443c15812032991c98b33b5424b17bcd55fe3575plougher if(bytes == -1) { 645fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("squashfs_opendir: inode block %d not found!\n", block_start); 646443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 647443c15812032991c98b33b5424b17bcd55fe3575plougher } 648443c15812032991c98b33b5424b17bcd55fe3575plougher block_ptr = inode_table + bytes + offset; 649443c15812032991c98b33b5424b17bcd55fe3575plougher 650443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 651443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_inode_header sinode; 652443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinode, block_ptr, sizeof(header.dir)); 653443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); 654443c15812032991c98b33b5424b17bcd55fe3575plougher } else 655443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&header.dir, block_ptr, sizeof(header.dir)); 656443c15812032991c98b33b5424b17bcd55fe3575plougher 657443c15812032991c98b33b5424b17bcd55fe3575plougher switch(header.dir.inode_type) { 658443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_DIR_TYPE: 659443c15812032991c98b33b5424b17bcd55fe3575plougher block_start = header.dir.start_block; 660443c15812032991c98b33b5424b17bcd55fe3575plougher offset = header.dir.offset; 661443c15812032991c98b33b5424b17bcd55fe3575plougher size = header.dir.file_size; 662443c15812032991c98b33b5424b17bcd55fe3575plougher break; 663443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_LDIR_TYPE: 664443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 665443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_ldir_inode_header sinode; 666443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sinode, block_ptr, sizeof(header.ldir)); 667443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); 668443c15812032991c98b33b5424b17bcd55fe3575plougher } else 669443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); 670443c15812032991c98b33b5424b17bcd55fe3575plougher block_start = header.ldir.start_block; 671443c15812032991c98b33b5424b17bcd55fe3575plougher offset = header.ldir.offset; 672443c15812032991c98b33b5424b17bcd55fe3575plougher size = header.ldir.file_size; 673443c15812032991c98b33b5424b17bcd55fe3575plougher break; 674443c15812032991c98b33b5424b17bcd55fe3575plougher default: 675443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("squashfs_opendir: inode not a directory\n"); 676443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 677443c15812032991c98b33b5424b17bcd55fe3575plougher } 678443c15812032991c98b33b5424b17bcd55fe3575plougher 679443c15812032991c98b33b5424b17bcd55fe3575plougher start = sBlk->directory_table_start + block_start; 680443c15812032991c98b33b5424b17bcd55fe3575plougher bytes = lookup_entry(directory_table_hash, start); 681443c15812032991c98b33b5424b17bcd55fe3575plougher 682443c15812032991c98b33b5424b17bcd55fe3575plougher if(bytes == -1) { 683fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("squashfs_opendir: directory block %d not found!\n", block_start); 684443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 685443c15812032991c98b33b5424b17bcd55fe3575plougher } 686443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += offset; 687443c15812032991c98b33b5424b17bcd55fe3575plougher size += bytes - 3; 688443c15812032991c98b33b5424b17bcd55fe3575plougher 689443c15812032991c98b33b5424b17bcd55fe3575plougher if((dir = malloc(sizeof(struct dir))) == NULL) { 690443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("squashfs_opendir: malloc failed!\n"); 691443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 692443c15812032991c98b33b5424b17bcd55fe3575plougher } 693443c15812032991c98b33b5424b17bcd55fe3575plougher 694443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dir_count = 0; 695443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry = 0; 696443c15812032991c98b33b5424b17bcd55fe3575plougher dir->mode = header.dir.mode; 697443c15812032991c98b33b5424b17bcd55fe3575plougher dir->uid = header.dir.uid; 698443c15812032991c98b33b5424b17bcd55fe3575plougher dir->guid = header.dir.guid; 699443c15812032991c98b33b5424b17bcd55fe3575plougher dir->mtime = header.dir.mtime; 700443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs = NULL; 701443c15812032991c98b33b5424b17bcd55fe3575plougher 702fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher while(bytes < size) { 703443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 704443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_header sdirh; 705443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); 706443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 707443c15812032991c98b33b5424b17bcd55fe3575plougher } else 708443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&dirh, directory_table + bytes, sizeof(dirh)); 709fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 710443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count = dirh.count + 1; 711fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); 712443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += sizeof(dirh); 713443c15812032991c98b33b5424b17bcd55fe3575plougher 714443c15812032991c98b33b5424b17bcd55fe3575plougher while(dir_count--) { 715443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 716443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_entry sdire; 717443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sdire, directory_table + bytes, sizeof(sdire)); 718443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 719443c15812032991c98b33b5424b17bcd55fe3575plougher } else 720443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(dire, directory_table + bytes, sizeof(dire)); 721443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += sizeof(*dire); 722443c15812032991c98b33b5424b17bcd55fe3575plougher 723443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(dire->name, directory_table + bytes, dire->size + 1); 724443c15812032991c98b33b5424b17bcd55fe3575plougher dire->name[dire->size + 1] = '\0'; 725fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); 726443c15812032991c98b33b5424b17bcd55fe3575plougher if((dir->dir_count % DIR_ENT_SIZE) == 0) { 727443c15812032991c98b33b5424b17bcd55fe3575plougher if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { 728443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("squashfs_opendir: realloc failed!\n"); 729443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 730443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 731443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 732443c15812032991c98b33b5424b17bcd55fe3575plougher } 733443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs = new_dir; 734443c15812032991c98b33b5424b17bcd55fe3575plougher } 735443c15812032991c98b33b5424b17bcd55fe3575plougher strcpy(dir->dirs[dir->dir_count].name, dire->name); 736443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].start_block = dirh.start_block; 737443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].offset = dire->offset; 738443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].type = dire->type; 739443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dir_count ++; 740443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += dire->size + 1; 741443c15812032991c98b33b5424b17bcd55fe3575plougher } 742443c15812032991c98b33b5424b17bcd55fe3575plougher } 743443c15812032991c98b33b5424b17bcd55fe3575plougher 744443c15812032991c98b33b5424b17bcd55fe3575plougher return dir; 745443c15812032991c98b33b5424b17bcd55fe3575plougher} 746443c15812032991c98b33b5424b17bcd55fe3575plougher 747443c15812032991c98b33b5424b17bcd55fe3575plougher 748443c15812032991c98b33b5424b17bcd55fe3575plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) 749443c15812032991c98b33b5424b17bcd55fe3575plougher{ 750443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 751443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 752443c15812032991c98b33b5424b17bcd55fe3575plougher 753443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 754443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 755443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 756443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 757443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 758443c15812032991c98b33b5424b17bcd55fe3575plougher 759443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 760443c15812032991c98b33b5424b17bcd55fe3575plougher} 761443c15812032991c98b33b5424b17bcd55fe3575plougher 762443c15812032991c98b33b5424b17bcd55fe3575plougher 763443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 764443c15812032991c98b33b5424b17bcd55fe3575plougher{ 765443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 766443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 767443c15812032991c98b33b5424b17bcd55fe3575plougher} 768443c15812032991c98b33b5424b17bcd55fe3575plougher 769443c15812032991c98b33b5424b17bcd55fe3575plougher 770b54566f5c433764830c29c83151691d0034de094plougherchar *get_component(char *target, char *targname) 771b54566f5c433764830c29c83151691d0034de094plougher{ 772b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 773b54566f5c433764830c29c83151691d0034de094plougher *target ++; 774b54566f5c433764830c29c83151691d0034de094plougher 775b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 776b54566f5c433764830c29c83151691d0034de094plougher *targname ++ = *target ++; 777b54566f5c433764830c29c83151691d0034de094plougher 778b54566f5c433764830c29c83151691d0034de094plougher *targname = '\0'; 779b54566f5c433764830c29c83151691d0034de094plougher 780b54566f5c433764830c29c83151691d0034de094plougher return target; 781b54566f5c433764830c29c83151691d0034de094plougher} 782b54566f5c433764830c29c83151691d0034de094plougher 783b54566f5c433764830c29c83151691d0034de094plougher 784b54566f5c433764830c29c83151691d0034de094plougherint matches(char *targname, char *name) 785b54566f5c433764830c29c83151691d0034de094plougher{ 786b54566f5c433764830c29c83151691d0034de094plougher if(*targname == '\0' || strcmp(targname, name) == 0) 787b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 788b54566f5c433764830c29c83151691d0034de094plougher 789b54566f5c433764830c29c83151691d0034de094plougher return FALSE; 790b54566f5c433764830c29c83151691d0034de094plougher} 791b54566f5c433764830c29c83151691d0034de094plougher 792b54566f5c433764830c29c83151691d0034de094plougher 793b54566f5c433764830c29c83151691d0034de094plougherint dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk, char *target) 794443c15812032991c98b33b5424b17bcd55fe3575plougher{ 795443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir *dir = squashfs_openddir(start_block, offset, sBlk); 796443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 797443c15812032991c98b33b5424b17bcd55fe3575plougher char *name, pathname[1024]; 798b54566f5c433764830c29c83151691d0034de094plougher char targname[1024]; 799b54566f5c433764830c29c83151691d0034de094plougher 800b54566f5c433764830c29c83151691d0034de094plougher target = get_component(target, targname); 801443c15812032991c98b33b5424b17bcd55fe3575plougher 802443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir == NULL) { 803fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); 804443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 805443c15812032991c98b33b5424b17bcd55fe3575plougher } 806443c15812032991c98b33b5424b17bcd55fe3575plougher 807443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) { 808443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); 809443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 810443c15812032991c98b33b5424b17bcd55fe3575plougher } 811443c15812032991c98b33b5424b17bcd55fe3575plougher 812443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 813fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); 814443c15812032991c98b33b5424b17bcd55fe3575plougher 815b54566f5c433764830c29c83151691d0034de094plougher 816b54566f5c433764830c29c83151691d0034de094plougher if(!matches(targname, name)) 817b54566f5c433764830c29c83151691d0034de094plougher continue; 818b54566f5c433764830c29c83151691d0034de094plougher 819443c15812032991c98b33b5424b17bcd55fe3575plougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 820fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 821443c15812032991c98b33b5424b17bcd55fe3575plougher if(lsonly || info) 822443c15812032991c98b33b5424b17bcd55fe3575plougher printf("%s\n", pathname); 823fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 824443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 825b54566f5c433764830c29c83151691d0034de094plougher dir_scan(pathname, start_block, offset, sBlk, target); 826443c15812032991c98b33b5424b17bcd55fe3575plougher else 827443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) 828443c15812032991c98b33b5424b17bcd55fe3575plougher create_inode(pathname, start_block, offset, sBlk); 829443c15812032991c98b33b5424b17bcd55fe3575plougher } 830443c15812032991c98b33b5424b17bcd55fe3575plougher 831443c15812032991c98b33b5424b17bcd55fe3575plougher !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE); 832443c15812032991c98b33b5424b17bcd55fe3575plougher 833443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 834443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 835443c15812032991c98b33b5424b17bcd55fe3575plougher 836443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 837443c15812032991c98b33b5424b17bcd55fe3575plougher} 838443c15812032991c98b33b5424b17bcd55fe3575plougher 839443c15812032991c98b33b5424b17bcd55fe3575plougher 840443c15812032991c98b33b5424b17bcd55fe3575plougherint read_super(squashfs_super_block *sBlk, char *source) 841443c15812032991c98b33b5424b17bcd55fe3575plougher{ 842443c15812032991c98b33b5424b17bcd55fe3575plougher read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); 843443c15812032991c98b33b5424b17bcd55fe3575plougher 844443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check it is a SQUASHFS superblock */ 845443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 846443c15812032991c98b33b5424b17bcd55fe3575plougher if(sBlk->s_magic != SQUASHFS_MAGIC) { 847443c15812032991c98b33b5424b17bcd55fe3575plougher if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { 848443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_super_block sblk; 849443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); 850443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); 851443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); 852443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 853443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 854443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Can't find a SQUASHFS superblock on %s\n", source); 855443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 856443c15812032991c98b33b5424b17bcd55fe3575plougher } 857443c15812032991c98b33b5424b17bcd55fe3575plougher } 858443c15812032991c98b33b5424b17bcd55fe3575plougher 859443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 860443c15812032991c98b33b5424b17bcd55fe3575plougher if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { 861443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", 862443c15812032991c98b33b5424b17bcd55fe3575plougher source, sBlk->s_major, sBlk->s_minor); 8639b5bf8c73c0eaf4f1ba0461615f4ed0d405a30ccplougher ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n"); 864443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 865443c15812032991c98b33b5424b17bcd55fe3575plougher } 866443c15812032991c98b33b5424b17bcd55fe3575plougher 867443c15812032991c98b33b5424b17bcd55fe3575plougher#if __BYTE_ORDER == __BIG_ENDIAN 868443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source); 869443c15812032991c98b33b5424b17bcd55fe3575plougher#else 870443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source); 871443c15812032991c98b33b5424b17bcd55fe3575plougher#endif 872443c15812032991c98b33b5424b17bcd55fe3575plougher 873443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); 874443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); 875443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); 876443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); 877443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); 878443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); 879443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); 880443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); 881443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tBlock size %d\n", sBlk->block_size); 882443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tNumber of fragments %d\n", sBlk->fragments); 883443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tNumber of inodes %d\n", sBlk->inodes); 884443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tNumber of uids %d\n", sBlk->no_uids); 885443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\tNumber of gids %d\n", sBlk->no_guids); 886fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start); 887fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start); 888fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start); 889fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start); 890443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("\n"); 891443c15812032991c98b33b5424b17bcd55fe3575plougher 892443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 893443c15812032991c98b33b5424b17bcd55fe3575plougher 894443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 895443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 896443c15812032991c98b33b5424b17bcd55fe3575plougher} 897443c15812032991c98b33b5424b17bcd55fe3575plougher 898443c15812032991c98b33b5424b17bcd55fe3575plougher 899443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 900b54566f5c433764830c29c83151691d0034de094plougher printf("unsquashfs version 1.1 (2006/07/09)\n");\ 9019b5bf8c73c0eaf4f1ba0461615f4ed0d405a30ccplougher printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \ 902443c15812032991c98b33b5424b17bcd55fe3575plougher printf("This program is free software; you can redistribute it and/or\n");\ 903443c15812032991c98b33b5424b17bcd55fe3575plougher printf("modify it under the terms of the GNU General Public License\n");\ 904443c15812032991c98b33b5424b17bcd55fe3575plougher printf("as published by the Free Software Foundation; either version 2,\n");\ 905443c15812032991c98b33b5424b17bcd55fe3575plougher printf("or (at your option) any later version.\n\n");\ 906443c15812032991c98b33b5424b17bcd55fe3575plougher printf("This program is distributed in the hope that it will be useful,\n");\ 907443c15812032991c98b33b5424b17bcd55fe3575plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ 908443c15812032991c98b33b5424b17bcd55fe3575plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ 909443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 910443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 911443c15812032991c98b33b5424b17bcd55fe3575plougher{ 912443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_super_block sBlk; 913443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 914443c15812032991c98b33b5424b17bcd55fe3575plougher int i, version = FALSE; 915b54566f5c433764830c29c83151691d0034de094plougher char *target = ""; 916443c15812032991c98b33b5424b17bcd55fe3575plougher 917443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 918443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 919443c15812032991c98b33b5424b17bcd55fe3575plougher break; 920443c15812032991c98b33b5424b17bcd55fe3575plougher if(strcmp(argv[i], "-version") == 0) { 921443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 922443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 923443c15812032991c98b33b5424b17bcd55fe3575plougher } else if(strcmp(argv[i], "-info") == 0) 924443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 925443c15812032991c98b33b5424b17bcd55fe3575plougher else if(strcmp(argv[i], "-ls") == 0) 926443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 927443c15812032991c98b33b5424b17bcd55fe3575plougher else if(strcmp(argv[i], "-dest") == 0) { 928443c15812032991c98b33b5424b17bcd55fe3575plougher if(++i == argc) 929443c15812032991c98b33b5424b17bcd55fe3575plougher goto options; 930443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 931443c15812032991c98b33b5424b17bcd55fe3575plougher } 932443c15812032991c98b33b5424b17bcd55fe3575plougher } 933443c15812032991c98b33b5424b17bcd55fe3575plougher 934443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 935443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 936443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 937b54566f5c433764830c29c83151691d0034de094plougher ERROR("SYNTAX: %s [-ls | -dest] filesystem [directory or filename to be extracted]\n", argv[0]); 938443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("\t-version\t\tprint version, licence and copyright information\n"); 939443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("\t-info\t\t\tprint files as they are unsquashed\n"); 940443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("\t-ls\t\t\tlist filesystem only\n"); 941443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("\t-dest <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); 942443c15812032991c98b33b5424b17bcd55fe3575plougher } 943443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 944443c15812032991c98b33b5424b17bcd55fe3575plougher } 945443c15812032991c98b33b5424b17bcd55fe3575plougher 946b54566f5c433764830c29c83151691d0034de094plougher if((i + 1) < argc) 947b54566f5c433764830c29c83151691d0034de094plougher target = argv[i + 1]; 948b54566f5c433764830c29c83151691d0034de094plougher 949443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 950443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); 951443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 952443c15812032991c98b33b5424b17bcd55fe3575plougher } 953443c15812032991c98b33b5424b17bcd55fe3575plougher 954443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_super(&sBlk, argv[i]) == FALSE) 955443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 956443c15812032991c98b33b5424b17bcd55fe3575plougher 957443c15812032991c98b33b5424b17bcd55fe3575plougher block_size = sBlk.block_size; 958443c15812032991c98b33b5424b17bcd55fe3575plougher if((fragment_data = malloc(block_size)) == NULL) 959443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 960443c15812032991c98b33b5424b17bcd55fe3575plougher 961443c15812032991c98b33b5424b17bcd55fe3575plougher if((file_data = malloc(block_size)) == NULL) 962443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 963443c15812032991c98b33b5424b17bcd55fe3575plougher 964443c15812032991c98b33b5424b17bcd55fe3575plougher if((data = malloc(block_size)) == NULL) 965443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate datan\n"); 966443c15812032991c98b33b5424b17bcd55fe3575plougher 967443c15812032991c98b33b5424b17bcd55fe3575plougher if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) 968443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 969443c15812032991c98b33b5424b17bcd55fe3575plougher 970443c15812032991c98b33b5424b17bcd55fe3575plougher memset(created_inode, 0, sBlk.inodes * sizeof(char *)); 971443c15812032991c98b33b5424b17bcd55fe3575plougher 972443c15812032991c98b33b5424b17bcd55fe3575plougher read_uids_guids(&sBlk); 973443c15812032991c98b33b5424b17bcd55fe3575plougher read_fragment_table(&sBlk); 974443c15812032991c98b33b5424b17bcd55fe3575plougher uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk); 975443c15812032991c98b33b5424b17bcd55fe3575plougher uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk); 976443c15812032991c98b33b5424b17bcd55fe3575plougher 977b54566f5c433764830c29c83151691d0034de094plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk, target); 978443c15812032991c98b33b5424b17bcd55fe3575plougher 979443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 980443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 981443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 982443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 983443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 984443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 985443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 986443c15812032991c98b33b5424b17bcd55fe3575plougher } 987443c15812032991c98b33b5424b17bcd55fe3575plougher 988443c15812032991c98b33b5424b17bcd55fe3575plougher} 989