1/* 2 * Unsquash a squashfs filesystem. This is a highly compressed read only 3 * filesystem. 4 * 5 * Copyright (c) 2009, 2010 6 * Phillip Lougher <phillip@lougher.demon.co.uk> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2, 11 * or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 * unsquashfs.h 23 */ 24 25#define TRUE 1 26#define FALSE 0 27#include <stdio.h> 28#include <sys/types.h> 29#include <unistd.h> 30#include <stdlib.h> 31#include <sys/stat.h> 32#include <fcntl.h> 33#include <errno.h> 34#include <string.h> 35#include <sys/mman.h> 36#include <utime.h> 37#include <pwd.h> 38#include <grp.h> 39#include <time.h> 40#include <regex.h> 41#include <fnmatch.h> 42#include <signal.h> 43#include <pthread.h> 44#include <math.h> 45#include <sys/ioctl.h> 46#include <sys/time.h> 47 48#ifndef linux 49#define __BYTE_ORDER BYTE_ORDER 50#define __BIG_ENDIAN BIG_ENDIAN 51#define __LITTLE_ENDIAN LITTLE_ENDIAN 52#else 53#include <endian.h> 54#endif 55 56#include "squashfs_fs.h" 57 58#ifdef SQUASHFS_TRACE 59#define TRACE(s, args...) \ 60 do { \ 61 pthread_mutex_lock(&screen_mutex); \ 62 if(progress_enabled) \ 63 printf("\n"); \ 64 printf("unsquashfs: "s, ## args); \ 65 pthread_mutex_unlock(&screen_mutex);\ 66 } while(0) 67#else 68#define TRACE(s, args...) 69#endif 70 71#define ERROR(s, args...) \ 72 do { \ 73 pthread_mutex_lock(&screen_mutex); \ 74 if(progress_enabled) \ 75 fprintf(stderr, "\n"); \ 76 fprintf(stderr, s, ## args); \ 77 pthread_mutex_unlock(&screen_mutex);\ 78 } while(0) 79 80#define EXIT_UNSQUASH(s, args...) \ 81 do { \ 82 pthread_mutex_lock(&screen_mutex); \ 83 fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ 84 pthread_mutex_unlock(&screen_mutex);\ 85 exit(1); \ 86 } while(0) 87 88#define CALCULATE_HASH(start) (start & 0xffff) 89 90/* 91 * Unified superblock containing fields for all superblocks 92 */ 93struct super_block { 94 struct squashfs_super_block s; 95 /* fields only used by squashfs 3 and earlier layouts */ 96 unsigned int no_uids; 97 unsigned int no_guids; 98 long long uid_start; 99 long long guid_start; 100}; 101 102struct hash_table_entry { 103 long long start; 104 int bytes; 105 struct hash_table_entry *next; 106}; 107 108struct inode { 109 int blocks; 110 char *block_ptr; 111 long long data; 112 int fragment; 113 int frag_bytes; 114 gid_t gid; 115 int inode_number; 116 int mode; 117 int offset; 118 long long start; 119 char *symlink; 120 time_t time; 121 int type; 122 uid_t uid; 123 char sparse; 124 unsigned int xattr; 125}; 126 127typedef struct squashfs_operations { 128 struct dir *(*squashfs_opendir)(unsigned int block_start, 129 unsigned int offset, struct inode **i); 130 void (*read_fragment)(unsigned int fragment, long long *start_block, 131 int *size); 132 int (*read_fragment_table)(); 133 void (*read_block_list)(unsigned int *block_list, char *block_ptr, 134 int blocks); 135 struct inode *(*read_inode)(unsigned int start_block, 136 unsigned int offset); 137 int (*read_uids_guids)(); 138} squashfs_operations; 139 140struct test { 141 int mask; 142 int value; 143 int position; 144 char mode; 145}; 146 147 148/* Cache status struct. Caches are used to keep 149 track of memory buffers passed between different threads */ 150struct cache { 151 int max_buffers; 152 int count; 153 int buffer_size; 154 int wait_free; 155 int wait_pending; 156 pthread_mutex_t mutex; 157 pthread_cond_t wait_for_free; 158 pthread_cond_t wait_for_pending; 159 struct cache_entry *free_list; 160 struct cache_entry *hash_table[65536]; 161}; 162 163/* struct describing a cache entry passed between threads */ 164struct cache_entry { 165 struct cache *cache; 166 long long block; 167 int size; 168 int used; 169 int error; 170 int pending; 171 struct cache_entry *hash_next; 172 struct cache_entry *hash_prev; 173 struct cache_entry *free_next; 174 struct cache_entry *free_prev; 175 char *data; 176}; 177 178/* struct describing queues used to pass data between threads */ 179struct queue { 180 int size; 181 int readp; 182 int writep; 183 pthread_mutex_t mutex; 184 pthread_cond_t empty; 185 pthread_cond_t full; 186 void **data; 187}; 188 189/* default size of fragment buffer in Mbytes */ 190#define FRAGMENT_BUFFER_DEFAULT 256 191/* default size of data buffer in Mbytes */ 192#define DATA_BUFFER_DEFAULT 256 193 194#define DIR_ENT_SIZE 16 195 196struct dir_ent { 197 char name[SQUASHFS_NAME_LEN + 1]; 198 unsigned int start_block; 199 unsigned int offset; 200 unsigned int type; 201}; 202 203struct dir { 204 int dir_count; 205 int cur_entry; 206 unsigned int mode; 207 uid_t uid; 208 gid_t guid; 209 unsigned int mtime; 210 unsigned int xattr; 211 struct dir_ent *dirs; 212}; 213 214struct file_entry { 215 int offset; 216 int size; 217 struct cache_entry *buffer; 218}; 219 220 221struct squashfs_file { 222 int fd; 223 int blocks; 224 long long file_size; 225 int mode; 226 uid_t uid; 227 gid_t gid; 228 time_t time; 229 char *pathname; 230 char sparse; 231 unsigned int xattr; 232}; 233 234struct path_entry { 235 char *name; 236 regex_t *preg; 237 struct pathname *paths; 238}; 239 240struct pathname { 241 int names; 242 struct path_entry *name; 243}; 244 245struct pathnames { 246 int count; 247 struct pathname *path[0]; 248}; 249#define PATHS_ALLOC_SIZE 10 250 251/* globals */ 252extern struct super_block sBlk; 253extern squashfs_operations s_ops; 254extern int swap; 255extern char *inode_table, *directory_table; 256extern struct hash_table_entry *inode_table_hash[65536], 257 *directory_table_hash[65536]; 258extern unsigned int *uid_table, *guid_table; 259extern pthread_mutex_t screen_mutex; 260extern int progress_enabled; 261extern int inode_number; 262extern int lookup_type[]; 263extern int fd; 264 265/* unsquashfs.c */ 266extern int lookup_entry(struct hash_table_entry **, long long); 267extern int read_fs_bytes(int fd, long long, int, void *); 268extern int read_block(int, long long, long long *, void *); 269 270/* unsquash-1.c */ 271extern void read_block_list_1(unsigned int *, char *, int); 272extern int read_fragment_table_1(); 273extern struct inode *read_inode_1(unsigned int, unsigned int); 274extern struct dir *squashfs_opendir_1(unsigned int, unsigned int, 275 struct inode **); 276extern int read_uids_guids_1(); 277 278/* unsquash-2.c */ 279extern void read_block_list_2(unsigned int *, char *, int); 280extern int read_fragment_table_2(); 281extern void read_fragment_2(unsigned int, long long *, int *); 282extern struct inode *read_inode_2(unsigned int, unsigned int); 283 284/* unsquash-3.c */ 285extern int read_fragment_table_3(); 286extern void read_fragment_3(unsigned int, long long *, int *); 287extern struct inode *read_inode_3(unsigned int, unsigned int); 288extern struct dir *squashfs_opendir_3(unsigned int, unsigned int, 289 struct inode **); 290 291/* unsquash-4.c */ 292extern int read_fragment_table_4(); 293extern void read_fragment_4(unsigned int, long long *, int *); 294extern struct inode *read_inode_4(unsigned int, unsigned int); 295extern struct dir *squashfs_opendir_4(unsigned int, unsigned int, 296 struct inode **); 297extern int read_uids_guids_4(); 298