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