unsquash-2.c revision 2751b4a665ee803e2fc81fc4e41fe2a24d551125
1/* 2 * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. 3 * 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 5 * Phillip Lougher <phillip@lougher.demon.co.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2, 10 * or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * 21 * unsquash-2.c 22 */ 23 24#include "unsquashfs.h" 25#include "squashfs_compat.h" 26 27static squashfs_fragment_entry_2 *fragment_table; 28 29void read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) 30{ 31 if(swap) { 32 unsigned int sblock_list[blocks]; 33 memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); 34 SQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks); 35 } else 36 memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); 37} 38 39 40void read_fragment_table_2() 41{ 42 int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); 43 unsigned int fragment_table_index[indexes]; 44 45 TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); 46 47 if(sBlk.fragments == 0) 48 return; 49 50 if((fragment_table = malloc(sBlk.fragments * 51 sizeof(squashfs_fragment_entry_2))) == NULL) 52 EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); 53 54 if(swap) { 55 unsigned int sfragment_table_index[indexes]; 56 57 read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); 58 SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); 59 } else 60 read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); 61 62 for(i = 0; i < indexes; i++) { 63 int length = read_block(fragment_table_index[i], NULL, 64 ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); 65 TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); 66 } 67 68 if(swap) { 69 squashfs_fragment_entry_2 sfragment; 70 for(i = 0; i < sBlk.fragments; i++) { 71 SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i])); 72 memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); 73 } 74 } 75} 76 77 78void read_fragment_2(unsigned int fragment, long long *start_block, int *size) 79{ 80 TRACE("read_fragment: reading fragment %d\n", fragment); 81 82 squashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment]; 83 *start_block = fragment_entry->start_block; 84 *size = fragment_entry->size; 85} 86 87 88struct inode *read_inode_2(unsigned int start_block, unsigned int offset) 89{ 90 static squashfs_inode_header_2 header; 91 long long start = sBlk.inode_table_start + start_block; 92 int bytes = lookup_entry(inode_table_hash, start); 93 char *block_ptr = inode_table + bytes + offset; 94 static struct inode i; 95 96 if(bytes == -1) 97 goto error; 98 99 if(swap) { 100 squashfs_base_inode_header_2 sinode; 101 memcpy(&sinode, block_ptr, sizeof(header.base)); 102 SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); 103 } else 104 memcpy(&header.base, block_ptr, sizeof(header.base)); 105 106 i.uid = (uid_t) uid_table[header.base.uid]; 107 i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; 108 i.mode = lookup_type[header.base.inode_type] | header.base.mode; 109 i.type = header.base.inode_type; 110 i.time = sBlk.mkfs_time; 111 i.inode_number = inode_number++; 112 113 switch(header.base.inode_type) { 114 case SQUASHFS_DIR_TYPE: { 115 squashfs_dir_inode_header_2 *inode = &header.dir; 116 117 if(swap) { 118 squashfs_dir_inode_header_2 sinode; 119 memcpy(&sinode, block_ptr, sizeof(header.dir)); 120 SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); 121 } else 122 memcpy(&header.dir, block_ptr, sizeof(header.dir)); 123 124 i.data = inode->file_size; 125 i.offset = inode->offset; 126 i.start = inode->start_block; 127 i.time = inode->mtime; 128 break; 129 } 130 case SQUASHFS_LDIR_TYPE: { 131 squashfs_ldir_inode_header_2 *inode = &header.ldir; 132 133 if(swap) { 134 squashfs_ldir_inode_header_2 sinode; 135 memcpy(&sinode, block_ptr, sizeof(header.ldir)); 136 SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); 137 } else 138 memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); 139 140 i.data = inode->file_size; 141 i.offset = inode->offset; 142 i.start = inode->start_block; 143 i.time = inode->mtime; 144 break; 145 } 146 case SQUASHFS_FILE_TYPE: { 147 squashfs_reg_inode_header_2 *inode = &header.reg; 148 149 if(swap) { 150 squashfs_reg_inode_header_2 sinode; 151 memcpy(&sinode, block_ptr, sizeof(sinode)); 152 SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); 153 } else 154 memcpy(inode, block_ptr, sizeof(*inode)); 155 156 i.data = inode->file_size; 157 i.time = inode->mtime; 158 i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 159 0 : inode->file_size % sBlk.block_size; 160 i.fragment = inode->fragment; 161 i.offset = inode->offset; 162 i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? 163 (inode->file_size + sBlk.block_size - 1) >> 164 sBlk.block_log : inode->file_size >> sBlk.block_log; 165 i.start = inode->start_block; 166 i.sparse = 0; 167 i.block_ptr = block_ptr + sizeof(*inode); 168 break; 169 } 170 case SQUASHFS_SYMLINK_TYPE: { 171 squashfs_symlink_inode_header_2 *inodep = &header.symlink; 172 173 if(swap) { 174 squashfs_symlink_inode_header_2 sinodep; 175 memcpy(&sinodep, block_ptr, sizeof(sinodep)); 176 SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); 177 } else 178 memcpy(inodep, block_ptr, sizeof(*inodep)); 179 180 i.symlink = malloc(inodep->symlink_size + 1); 181 if(i.symlink == NULL) 182 EXIT_UNSQUASH("read_inode: failed to malloc symlink data\n"); 183 strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); 184 i.symlink[inodep->symlink_size] = '\0'; 185 i.data = inodep->symlink_size; 186 break; 187 } 188 case SQUASHFS_BLKDEV_TYPE: 189 case SQUASHFS_CHRDEV_TYPE: { 190 squashfs_dev_inode_header_2 *inodep = &header.dev; 191 192 if(swap) { 193 squashfs_dev_inode_header_2 sinodep; 194 memcpy(&sinodep, block_ptr, sizeof(sinodep)); 195 SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); 196 } else 197 memcpy(inodep, block_ptr, sizeof(*inodep)); 198 199 i.data = inodep->rdev; 200 break; 201 } 202 case SQUASHFS_FIFO_TYPE: 203 case SQUASHFS_SOCKET_TYPE: 204 i.data = 0; 205 break; 206 default: 207 ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); 208 return NULL; 209 } 210 return &i; 211 212error: 213 return NULL; 214} 215