unsquashfs.c revision 1b42101056befe25b5f19d5b099e806a2ecee9cd
1443c15812032991c98b33b5424b17bcd55fe3575plougher/* 2443c15812032991c98b33b5424b17bcd55fe3575plougher * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. 3443c15812032991c98b33b5424b17bcd55fe3575plougher * 48888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 579df93becb68081effabebba3006c794be308598plougher * Phillip Lougher <phillip@lougher.demon.co.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 24ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher#define CONFIG_SQUASHFS_1_0_COMPATIBILITY 2502bc3bcabf2b219f63961f07293b83629948f026plougher#define CONFIG_SQUASHFS_2_0_COMPATIBILITY 2602bc3bcabf2b219f63961f07293b83629948f026plougher 27443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRUE 1 28443c15812032991c98b33b5424b17bcd55fe3575plougher#define FALSE 0 29443c15812032991c98b33b5424b17bcd55fe3575plougher#include <stdio.h> 30443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/types.h> 31daa5fa85f54a8deaaaa294797fcc6be9ab7a597bplougher#include <unistd.h> 328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#include <stdlib.h> 33443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/stat.h> 34443c15812032991c98b33b5424b17bcd55fe3575plougher#include <fcntl.h> 35443c15812032991c98b33b5424b17bcd55fe3575plougher#include <errno.h> 36443c15812032991c98b33b5424b17bcd55fe3575plougher#include <string.h> 37443c15812032991c98b33b5424b17bcd55fe3575plougher#include <zlib.h> 38443c15812032991c98b33b5424b17bcd55fe3575plougher#include <sys/mman.h> 39443c15812032991c98b33b5424b17bcd55fe3575plougher#include <utime.h> 40476dcb48b24efff22caa970f000e151f1b28918dplougher#include <pwd.h> 41476dcb48b24efff22caa970f000e151f1b28918dplougher#include <grp.h> 4288facddfd83e48a907b82210ddccbb4f84d80aecplougher#include <time.h> 434dba330d7b952f2f044d38e342e2ae3ea78910d6plougher#include <regex.h> 444dba330d7b952f2f044d38e342e2ae3ea78910d6plougher#include <fnmatch.h> 458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#include <signal.h> 468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#include <pthread.h> 47eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher#include <math.h> 48eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher#include <sys/ioctl.h> 49eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher#include <sys/time.h> 50443c15812032991c98b33b5424b17bcd55fe3575plougher 51443c15812032991c98b33b5424b17bcd55fe3575plougher#ifndef linux 52443c15812032991c98b33b5424b17bcd55fe3575plougher#define __BYTE_ORDER BYTE_ORDER 53443c15812032991c98b33b5424b17bcd55fe3575plougher#define __BIG_ENDIAN BIG_ENDIAN 54443c15812032991c98b33b5424b17bcd55fe3575plougher#define __LITTLE_ENDIAN LITTLE_ENDIAN 55443c15812032991c98b33b5424b17bcd55fe3575plougher#else 56443c15812032991c98b33b5424b17bcd55fe3575plougher#include <endian.h> 57443c15812032991c98b33b5424b17bcd55fe3575plougher#endif 58443c15812032991c98b33b5424b17bcd55fe3575plougher 598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#include "squashfs_fs.h" 60443c15812032991c98b33b5424b17bcd55fe3575plougher#include "read_fs.h" 61443c15812032991c98b33b5424b17bcd55fe3575plougher#include "global.h" 62443c15812032991c98b33b5424b17bcd55fe3575plougher 631b42101056befe25b5f19d5b099e806a2ecee9cdplougher#define PRINTF(s, args...) do { \ 641b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); \ 651b42101056befe25b5f19d5b099e806a2ecee9cdplougher printf(s, ## args); \ 661b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex);\ 671b42101056befe25b5f19d5b099e806a2ecee9cdplougher } while(0) 681b42101056befe25b5f19d5b099e806a2ecee9cdplougher 69443c15812032991c98b33b5424b17bcd55fe3575plougher#ifdef SQUASHFS_TRACE 70443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRACE(s, args...) do { \ 711b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); \ 724dba330d7b952f2f044d38e342e2ae3ea78910d6plougher printf("unsquashfs: "s, ## args); \ 731b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex);\ 74443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 75443c15812032991c98b33b5424b17bcd55fe3575plougher#else 76443c15812032991c98b33b5424b17bcd55fe3575plougher#define TRACE(s, args...) 77443c15812032991c98b33b5424b17bcd55fe3575plougher#endif 78443c15812032991c98b33b5424b17bcd55fe3575plougher 79443c15812032991c98b33b5424b17bcd55fe3575plougher#define ERROR(s, args...) do { \ 801b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); \ 81443c15812032991c98b33b5424b17bcd55fe3575plougher fprintf(stderr, s, ## args); \ 821b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex);\ 83443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 84443c15812032991c98b33b5424b17bcd55fe3575plougher 85443c15812032991c98b33b5424b17bcd55fe3575plougher#define EXIT_UNSQUASH(s, args...) do { \ 861b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); \ 87443c15812032991c98b33b5424b17bcd55fe3575plougher fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ 881b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex);\ 894dba330d7b952f2f044d38e342e2ae3ea78910d6plougher exit(1); \ 90443c15812032991c98b33b5424b17bcd55fe3575plougher } while(0) 91443c15812032991c98b33b5424b17bcd55fe3575plougher 928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#define CALCULATE_HASH(start) (start & 0xffff) 938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 94443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry { 95443c15812032991c98b33b5424b17bcd55fe3575plougher int start; 96443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes; 97443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *next; 98443c15812032991c98b33b5424b17bcd55fe3575plougher}; 99443c15812032991c98b33b5424b17bcd55fe3575plougher 1006f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherstruct inode { 1016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int blocks; 1026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher char *block_ptr; 10347fc2f0b451e12cddb0cc482019e6abe5bd59d46plougher long long data; 1046f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int fragment; 1056f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int frag_bytes; 1066f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher gid_t gid; 1076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int inode_number; 1086f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int mode; 1096f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int offset; 1106f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher long long start; 1116f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher char symlink[65536]; 1126f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher time_t time; 1136f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int type; 1146f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher uid_t uid; 1156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher}; 116eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 117eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughertypedef struct squashfs_operations { 118eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); 119eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); 120eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher void (*read_fragment_table)(); 121eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} squashfs_operations; 1246f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 125476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test { 126476dcb48b24efff22caa970f000e151f1b28918dplougher int mask; 127476dcb48b24efff22caa970f000e151f1b28918dplougher int value; 128476dcb48b24efff22caa970f000e151f1b28918dplougher int position; 129476dcb48b24efff22caa970f000e151f1b28918dplougher char mode; 130476dcb48b24efff22caa970f000e151f1b28918dplougher}; 131476dcb48b24efff22caa970f000e151f1b28918dplougher 1328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Cache status struct. Caches are used to keep 1348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher track of memory buffers passed between different threads */ 1358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache { 1368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int max_buffers; 1378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int count; 1388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int buffer_size; 1398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int wait_free; 1408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int wait_pending; 1418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_t mutex; 1428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_t wait_for_free; 1438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_t wait_for_pending; 1448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *free_list; 1458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *hash_table[65536]; 1468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* struct describing a cache entry passed between threads */ 1498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry { 1508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache; 1518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long block; 1528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 1538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int used; 1548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int error; 1558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int pending; 1568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *hash_next; 1578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *hash_prev; 1588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *free_next; 1598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *free_prev; 1608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char *data; 1618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* struct describing queues used to pass data between threads */ 1648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue { 1658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 1668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int readp; 1678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int writep; 1688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_t mutex; 1698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_t empty; 1708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_t full; 1718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void **data; 1728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *fragment_cache, *data_cache; 1758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *to_reader, *to_deflate, *to_writer, *from_writer; 1768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_t *thread, *deflator_thread; 1778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_mutex_t fragment_mutex; 1788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* user options that control parallelisation */ 1808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint processors = -1; 1818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* default size of fragment buffer in Mbytes */ 1828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#define FRAGMENT_BUFFER_DEFAULT 256 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* default size of data buffer in Mbytes */ 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#define DATA_BUFFER_DEFAULT 256 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18602bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_super_block sBlk; 18702bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_operations s_ops; 18802bc3bcabf2b219f63961f07293b83629948f026plougher 1899dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, 1909dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher dev_count = 0, fifo_count = 0; 191443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 192443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 193443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 194443c15812032991c98b33b5424b17bcd55fe3575ploughersquashfs_fragment_entry *fragment_table; 19502bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_fragment_entry_2 *fragment_table_2; 196443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 197443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 198443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 199443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 200443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 201443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 202ae271cc93e3684d5314bcdc45b631e497ae43166plougherunsigned int block_log; 2034dba330d7b952f2f044d38e342e2ae3ea78910d6plougherint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; 204443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 2059dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint root_process; 206eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint columns; 207eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint rotate = 0; 2081b42101056befe25b5f19d5b099e806a2ecee9cdplougherpthread_mutex_t screen_mutex; 209eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherpthread_cond_t progress_wait; 2101b42101056befe25b5f19d5b099e806a2ecee9cdplougherint progress = TRUE, progress_enabled = FALSE; 211eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int total_blocks = 0, total_files = 0, total_inodes = 0; 212eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int cur_blocks = 0; 213443c15812032991c98b33b5424b17bcd55fe3575plougher 214476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 215476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 216476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 217476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 218476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 219476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 220476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 221476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 222476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 223476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 224476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG 225476dcb48b24efff22caa970f000e151f1b28918dplougher}; 226476dcb48b24efff22caa970f000e151f1b28918dplougher 227476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 228476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 229476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 230476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 231476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 232476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 233476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 234476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 235476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 236476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 237476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 238476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 239476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 240476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 241476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 242476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 243476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 244476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 245476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 246476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 247476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 248476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 252eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 253eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar(); 254eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 255eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 256eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 257eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 258eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 259eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 2601b42101056befe25b5f19d5b099e806a2ecee9cdplougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); 261eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 262eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 263eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 264eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 265eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2671b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 2681b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 2691b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 2701b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 2711b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 2721b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 2738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 2748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 2768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 2788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 2798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(queue); 2828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 2838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 2868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 2878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 2888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 2908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 2928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 2988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 3008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 3028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 3078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 3088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3118888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 3128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 3148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 3158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 3178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 3188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 3218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 3228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 3238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 3258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 3298888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 3308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 3328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 3348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 3358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 3368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 3378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 3388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 3438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 3458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 3468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 3478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; 3488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 3498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 3508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 3528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 3568888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 3578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 3598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 3608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 3618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 3628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 3638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 3648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 3658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 3668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 3718888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 3728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->free_prev == NULL && entry->free_next == NULL) 3748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 3758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 376222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 3778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 3808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 3818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 3828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 3838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 3848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 3858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 3928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 3948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 3998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 4008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 4018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 4028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 4038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 4048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 4058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 4068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 4078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 4088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 4148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 4158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* Get a block out of the cache. If the block isn't in the cache 4168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * it is added and queued to the reader() and deflate() threads for reading 4178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * off disk and decompression. The cache grows until max_blocks is reached, 4188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * once this occurs existing discarded blocks on the free list are reused */ 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 4218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 4238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 4258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 4268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 4278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 4298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* found the block in the cache, increment used count and 4308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * if necessary remove from free list so it won't disappear 4318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 4328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 4338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 4348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 4358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 4368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in the cache */ 4378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* first try to allocate new block */ 4398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 4408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 4418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 4428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher goto failed; 4438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 4448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->data == NULL) { 4458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(entry); 4468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher goto failed; 4478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 4498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 4508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 4518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 4528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* try to get from free list */ 4538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 4548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 4558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&cache->wait_for_free, &cache->mutex); 4568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 4588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 4598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 4608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* initialise block and insert into the hash table */ 4638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 4648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 4658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 4668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 4678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 4688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 4698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* queue to read thread to read and ultimately (via the decompress 4718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * threads) decompress the buffer 4728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 4738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 4748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 4758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 4788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherfailed: 4808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 4818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 4828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4858888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 4868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 4878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* mark cache entry as being complete, reading and (if necessary) 4888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 4898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 4908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * becomes ready but with an error... */ 4918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 4938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 4948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* if the wait_pending flag is set, one or more threads may be waiting on 4968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * this buffer */ 4978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 4988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 4998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 5008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 5018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 5038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 5048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5068888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 5078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 5088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* wait for this cache entry to become ready, when reading and (if necessary) 5098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place */ 5108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 5118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 5138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 5148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); 5158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 5168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 5188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 5198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5218888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 5228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 5238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* finished with this cache entry, once the usage count reaches zero it 5248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * can be reused and is put onto the free list. As it remains accessible 5258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * via the hash table it can be found getting a new lease of life before it 5268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * is reused. */ 5278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 5288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 5308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 5318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 5328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* if the wait_free flag is set, one or more threads may be waiting on 5348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * this buffer */ 5358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 5368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 5378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 5388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 5398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 5408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 5418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 5428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 543476dcb48b24efff22caa970f000e151f1b28918dplougher 544476dcb48b24efff22caa970f000e151f1b28918dplougher 545476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 546476dcb48b24efff22caa970f000e151f1b28918dplougher{ 547476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 548476dcb48b24efff22caa970f000e151f1b28918dplougher 549476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 550476dcb48b24efff22caa970f000e151f1b28918dplougher 551476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 552476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 553476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 554476dcb48b24efff22caa970f000e151f1b28918dplougher } 555476dcb48b24efff22caa970f000e151f1b28918dplougher 556476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 557476dcb48b24efff22caa970f000e151f1b28918dplougher} 558476dcb48b24efff22caa970f000e151f1b28918dplougher 559476dcb48b24efff22caa970f000e151f1b28918dplougher 5603edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 5616f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 562476dcb48b24efff22caa970f000e151f1b28918dplougher{ 5636f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher char str[11], dummy[100], dummy2[100], *userstr, *groupstr; 5646f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 565476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 566476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 56788facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 568476dcb48b24efff22caa970f000e151f1b28918dplougher 569476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 570476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 571476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 572476dcb48b24efff22caa970f000e151f1b28918dplougher } 573476dcb48b24efff22caa970f000e151f1b28918dplougher 5746f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((user = getpwuid(inode->uid)) == NULL) { 5756f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy, "%d", inode->uid); 5763edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = dummy; 5773edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5783edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 5793edfa57b6a463f7d441d995559143f4861d62e98plougher 5806f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((group = getgrgid(inode->gid)) == NULL) { 5816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy2, "%d", inode->gid); 5823edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = dummy2; 5833edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5843edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 5853edfa57b6a463f7d441d995559143f4861d62e98plougher 5866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 5873edfa57b6a463f7d441d995559143f4861d62e98plougher 5886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 5893edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 5903edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 5913edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 5923edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 5933edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 5943edfa57b6a463f7d441d995559143f4861d62e98plougher padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); 5953edfa57b6a463f7d441d995559143f4861d62e98plougher 596caf2f0f593c7f14a4e7e151eeeed773c72578f69plougher printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); 5973edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5983edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 5993edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 6003edfa57b6a463f7d441d995559143f4861d62e98plougher padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; 6013edfa57b6a463f7d441d995559143f4861d62e98plougher 60247fc2f0b451e12cddb0cc482019e6abe5bd59d46plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); 6033edfa57b6a463f7d441d995559143f4861d62e98plougher break; 6043edfa57b6a463f7d441d995559143f4861d62e98plougher } 605476dcb48b24efff22caa970f000e151f1b28918dplougher 6066f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 60788facddfd83e48a907b82210ddccbb4f84d80aecplougher 60888facddfd83e48a907b82210ddccbb4f84d80aecplougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); 6096f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 6106f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 6113edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 6123edfa57b6a463f7d441d995559143f4861d62e98plougher 613476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 614476dcb48b24efff22caa970f000e151f1b28918dplougher} 615476dcb48b24efff22caa970f000e151f1b28918dplougher 616443c15812032991c98b33b5424b17bcd55fe3575plougher 617443c15812032991c98b33b5424b17bcd55fe3575plougherint add_entry(struct hash_table_entry *hash_table[], int start, int bytes) 618443c15812032991c98b33b5424b17bcd55fe3575plougher{ 619443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 620443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 621443c15812032991c98b33b5424b17bcd55fe3575plougher 622443c15812032991c98b33b5424b17bcd55fe3575plougher if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { 623443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("add_hash: out of memory in malloc\n"); 624443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 625443c15812032991c98b33b5424b17bcd55fe3575plougher } 626443c15812032991c98b33b5424b17bcd55fe3575plougher 627443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 628443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 629443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 630443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 631443c15812032991c98b33b5424b17bcd55fe3575plougher 632443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 633443c15812032991c98b33b5424b17bcd55fe3575plougher} 634443c15812032991c98b33b5424b17bcd55fe3575plougher 635443c15812032991c98b33b5424b17bcd55fe3575plougher 636443c15812032991c98b33b5424b17bcd55fe3575plougherint lookup_entry(struct hash_table_entry *hash_table[], int start) 637443c15812032991c98b33b5424b17bcd55fe3575plougher{ 638443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 639443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 640443c15812032991c98b33b5424b17bcd55fe3575plougher 6419dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 6429dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 643443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 644443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 645443c15812032991c98b33b5424b17bcd55fe3575plougher 646443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 647443c15812032991c98b33b5424b17bcd55fe3575plougher} 648443c15812032991c98b33b5424b17bcd55fe3575plougher 649443c15812032991c98b33b5424b17bcd55fe3575plougher 650443c15812032991c98b33b5424b17bcd55fe3575plougherint read_bytes(long long byte, int bytes, char *buff) 651443c15812032991c98b33b5424b17bcd55fe3575plougher{ 652443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 653443c15812032991c98b33b5424b17bcd55fe3575plougher 654fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); 655fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 656443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 6575d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 658443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 659443c15812032991c98b33b5424b17bcd55fe3575plougher } 660443c15812032991c98b33b5424b17bcd55fe3575plougher 661443c15812032991c98b33b5424b17bcd55fe3575plougher if(read(fd, buff, bytes) == -1) { 662443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Read on destination failed because %s\n", strerror(errno)); 663443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 664443c15812032991c98b33b5424b17bcd55fe3575plougher } 665443c15812032991c98b33b5424b17bcd55fe3575plougher 666443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 667443c15812032991c98b33b5424b17bcd55fe3575plougher} 668443c15812032991c98b33b5424b17bcd55fe3575plougher 669443c15812032991c98b33b5424b17bcd55fe3575plougher 67002bc3bcabf2b219f63961f07293b83629948f026plougherint read_block(long long start, long long *next, char *block) 671443c15812032991c98b33b5424b17bcd55fe3575plougher{ 672443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 673443c15812032991c98b33b5424b17bcd55fe3575plougher int offset = 2; 674443c15812032991c98b33b5424b17bcd55fe3575plougher 675443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 676443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, block) == FALSE) 677fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 678443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[1] = block[0]; 679443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[0] = block[1]; 680443c15812032991c98b33b5424b17bcd55fe3575plougher } else 681443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, (char *)&c_byte) == FALSE) 682fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 683fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 684fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); 685443c15812032991c98b33b5424b17bcd55fe3575plougher 68602bc3bcabf2b219f63961f07293b83629948f026plougher if(SQUASHFS_CHECK_DATA(sBlk.flags)) 687443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 688443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED(c_byte)) { 689443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[SQUASHFS_METADATA_SIZE]; 690443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 691443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = SQUASHFS_METADATA_SIZE; 692443c15812032991c98b33b5424b17bcd55fe3575plougher 693443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 694443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, buffer) == FALSE) 695fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 696443c15812032991c98b33b5424b17bcd55fe3575plougher 697545404219cdd79c1e06ac7d0698d02a15240c4c3plougher res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte); 698545404219cdd79c1e06ac7d0698d02a15240c4c3plougher 699545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(res != Z_OK) { 700443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 701443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough memory\n"); 702443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 703443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough room in output buffer\n"); 704443c15812032991c98b33b5424b17bcd55fe3575plougher else 705443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, unknown error %d\n", res); 706fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 707443c15812032991c98b33b5424b17bcd55fe3575plougher } 708443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 709443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 710443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 711443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 712443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 713443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, block) == FALSE) 714fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 715443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 716443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 717443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 718443c15812032991c98b33b5424b17bcd55fe3575plougher } 719fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 720fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 721fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 722443c15812032991c98b33b5424b17bcd55fe3575plougher} 723443c15812032991c98b33b5424b17bcd55fe3575plougher 724443c15812032991c98b33b5424b17bcd55fe3575plougher 725443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 726443c15812032991c98b33b5424b17bcd55fe3575plougher{ 727443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 728443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = block_size; 729443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 730443c15812032991c98b33b5424b17bcd55fe3575plougher 731fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 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"); 732fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 733443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 734443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, data) == FALSE) 735443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 736443c15812032991c98b33b5424b17bcd55fe3575plougher 737545404219cdd79c1e06ac7d0698d02a15240c4c3plougher res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte); 738545404219cdd79c1e06ac7d0698d02a15240c4c3plougher 739545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(res != Z_OK) { 740443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 741443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough memory\n"); 742443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 743443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, not enough room in output buffer\n"); 744443c15812032991c98b33b5424b17bcd55fe3575plougher else 745443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("zlib::uncompress failed, unknown error %d\n", res); 746443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 747443c15812032991c98b33b5424b17bcd55fe3575plougher } 748443c15812032991c98b33b5424b17bcd55fe3575plougher 749443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 750443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 751443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, block) == FALSE) 752443c15812032991c98b33b5424b17bcd55fe3575plougher return 0; 753443c15812032991c98b33b5424b17bcd55fe3575plougher 754443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 755443c15812032991c98b33b5424b17bcd55fe3575plougher } 756443c15812032991c98b33b5424b17bcd55fe3575plougher} 757443c15812032991c98b33b5424b17bcd55fe3575plougher 758443c15812032991c98b33b5424b17bcd55fe3575plougher 759545404219cdd79c1e06ac7d0698d02a15240c4c3ploughervoid read_block_list(unsigned int *block_list, char *block_ptr, int blocks) 760ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher{ 761ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(swap) { 762ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher unsigned int sblock_list[blocks]; 763ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); 764ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); 765ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else 766ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); 767ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher} 768ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 769ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 770545404219cdd79c1e06ac7d0698d02a15240c4c3ploughervoid read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) 771ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher{ 772ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher unsigned short block_size; 773ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher int i; 774ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 775ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher for(i = 0; i < blocks; i++, block_ptr += 2) { 776ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(swap) { 777ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher unsigned short sblock_size; 778ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); 779ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); 780ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else 781ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(&block_size, block_ptr, sizeof(unsigned short)); 782ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); 783ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 784ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher} 785ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 786ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 78702bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_inode_table(long long start, long long end) 788443c15812032991c98b33b5424b17bcd55fe3575plougher{ 789443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 790443c15812032991c98b33b5424b17bcd55fe3575plougher 791443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 792443c15812032991c98b33b5424b17bcd55fe3575plougher if((size - bytes < SQUASHFS_METADATA_SIZE) && 7939dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher ((inode_table = realloc(inode_table, size += 7949dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher SQUASHFS_METADATA_SIZE)) == NULL)) 795443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); 796443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_inode_table: reading block 0x%llx\n", start); 797443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 79802bc3bcabf2b219f63961f07293b83629948f026plougher if((res = read_block(start, &start, inode_table + bytes)) == 0) { 799443c15812032991c98b33b5424b17bcd55fe3575plougher free(inode_table); 800443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); 801443c15812032991c98b33b5424b17bcd55fe3575plougher } 802443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 803443c15812032991c98b33b5424b17bcd55fe3575plougher } 804443c15812032991c98b33b5424b17bcd55fe3575plougher} 805443c15812032991c98b33b5424b17bcd55fe3575plougher 806443c15812032991c98b33b5424b17bcd55fe3575plougher 8076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) 808443c15812032991c98b33b5424b17bcd55fe3575plougher{ 8096f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 810443c15812032991c98b33b5424b17bcd55fe3575plougher 811443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 812443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); 813443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 814443c15812032991c98b33b5424b17bcd55fe3575plougher } 815443c15812032991c98b33b5424b17bcd55fe3575plougher 8169dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 8176f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 818443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); 819443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 820443c15812032991c98b33b5424b17bcd55fe3575plougher } 8219dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 8229dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 8239dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 8249dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 8259dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); 8269dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 827443c15812032991c98b33b5424b17bcd55fe3575plougher } 828443c15812032991c98b33b5424b17bcd55fe3575plougher 829443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 830443c15812032991c98b33b5424b17bcd55fe3575plougher} 831443c15812032991c98b33b5424b17bcd55fe3575plougher 832443c15812032991c98b33b5424b17bcd55fe3575plougher 83302bc3bcabf2b219f63961f07293b83629948f026ploughervoid read_uids_guids() 834443c15812032991c98b33b5424b17bcd55fe3575plougher{ 83502bc3bcabf2b219f63961f07293b83629948f026plougher if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) 836443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); 837443c15812032991c98b33b5424b17bcd55fe3575plougher 83802bc3bcabf2b219f63961f07293b83629948f026plougher guid_table = uid_table + sBlk.no_uids; 839443c15812032991c98b33b5424b17bcd55fe3575plougher 840fc9aa5457df027969c6616cdf93fc1945ad7688eplougher if(swap) { 84102bc3bcabf2b219f63961f07293b83629948f026plougher unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; 842fc9aa5457df027969c6616cdf93fc1945ad7688eplougher 84302bc3bcabf2b219f63961f07293b83629948f026plougher if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) 8449dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher * sizeof(unsigned int), (char *) suid_table) == 8459dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher FALSE) 846fc9aa5457df027969c6616cdf93fc1945ad7688eplougher EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); 84702bc3bcabf2b219f63961f07293b83629948f026plougher SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); 848fc9aa5457df027969c6616cdf93fc1945ad7688eplougher } else 84902bc3bcabf2b219f63961f07293b83629948f026plougher if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) 8509dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher * sizeof(unsigned int), (char *) uid_table) == 8519dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher FALSE) 852fc9aa5457df027969c6616cdf93fc1945ad7688eplougher EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); 853443c15812032991c98b33b5424b17bcd55fe3575plougher} 854443c15812032991c98b33b5424b17bcd55fe3575plougher 855443c15812032991c98b33b5424b17bcd55fe3575plougher 85602bc3bcabf2b219f63961f07293b83629948f026ploughervoid read_fragment_table() 857443c15812032991c98b33b5424b17bcd55fe3575plougher{ 85802bc3bcabf2b219f63961f07293b83629948f026plougher int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); 859443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_index fragment_table_index[indexes]; 860443c15812032991c98b33b5424b17bcd55fe3575plougher 86102bc3bcabf2b219f63961f07293b83629948f026plougher TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); 8629dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 86302bc3bcabf2b219f63961f07293b83629948f026plougher if(sBlk.fragments == 0) 864443c15812032991c98b33b5424b17bcd55fe3575plougher return; 865443c15812032991c98b33b5424b17bcd55fe3575plougher 8669dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((fragment_table = (squashfs_fragment_entry *) 86702bc3bcabf2b219f63961f07293b83629948f026plougher malloc(sBlk.fragments * 8689dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher sizeof(squashfs_fragment_entry))) == NULL) 869443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); 870443c15812032991c98b33b5424b17bcd55fe3575plougher 871443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 872443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_index sfragment_table_index[indexes]; 873443c15812032991c98b33b5424b17bcd55fe3575plougher 87402bc3bcabf2b219f63961f07293b83629948f026plougher read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); 875443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); 876443c15812032991c98b33b5424b17bcd55fe3575plougher } else 87702bc3bcabf2b219f63961f07293b83629948f026plougher read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); 878443c15812032991c98b33b5424b17bcd55fe3575plougher 879443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 0; i < indexes; i++) { 8809dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher int length = read_block(fragment_table_index[i], NULL, 88102bc3bcabf2b219f63961f07293b83629948f026plougher ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); 882fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); 883443c15812032991c98b33b5424b17bcd55fe3575plougher } 884443c15812032991c98b33b5424b17bcd55fe3575plougher 885443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 886443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_fragment_entry sfragment; 88702bc3bcabf2b219f63961f07293b83629948f026plougher for(i = 0; i < sBlk.fragments; i++) { 888443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); 889443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); 890443c15812032991c98b33b5424b17bcd55fe3575plougher } 891443c15812032991c98b33b5424b17bcd55fe3575plougher } 892443c15812032991c98b33b5424b17bcd55fe3575plougher} 893443c15812032991c98b33b5424b17bcd55fe3575plougher 894443c15812032991c98b33b5424b17bcd55fe3575plougher 89502bc3bcabf2b219f63961f07293b83629948f026ploughervoid read_fragment_table_2() 89602bc3bcabf2b219f63961f07293b83629948f026plougher{ 89702bc3bcabf2b219f63961f07293b83629948f026plougher int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); 89802bc3bcabf2b219f63961f07293b83629948f026plougher unsigned int fragment_table_index[indexes]; 89902bc3bcabf2b219f63961f07293b83629948f026plougher 90002bc3bcabf2b219f63961f07293b83629948f026plougher TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); 90102bc3bcabf2b219f63961f07293b83629948f026plougher 90202bc3bcabf2b219f63961f07293b83629948f026plougher if(sBlk.fragments == 0) 90302bc3bcabf2b219f63961f07293b83629948f026plougher return; 90402bc3bcabf2b219f63961f07293b83629948f026plougher 90502bc3bcabf2b219f63961f07293b83629948f026plougher if((fragment_table_2 = (squashfs_fragment_entry_2 *) 90602bc3bcabf2b219f63961f07293b83629948f026plougher malloc(sBlk.fragments * 90702bc3bcabf2b219f63961f07293b83629948f026plougher sizeof(squashfs_fragment_entry))) == NULL) 90802bc3bcabf2b219f63961f07293b83629948f026plougher EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); 90902bc3bcabf2b219f63961f07293b83629948f026plougher 91002bc3bcabf2b219f63961f07293b83629948f026plougher if(swap) { 91102bc3bcabf2b219f63961f07293b83629948f026plougher unsigned int sfragment_table_index[indexes]; 91202bc3bcabf2b219f63961f07293b83629948f026plougher 91302bc3bcabf2b219f63961f07293b83629948f026plougher read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); 91402bc3bcabf2b219f63961f07293b83629948f026plougher SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); 91502bc3bcabf2b219f63961f07293b83629948f026plougher } else 91602bc3bcabf2b219f63961f07293b83629948f026plougher read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); 91702bc3bcabf2b219f63961f07293b83629948f026plougher 91802bc3bcabf2b219f63961f07293b83629948f026plougher for(i = 0; i < indexes; i++) { 91902bc3bcabf2b219f63961f07293b83629948f026plougher int length = read_block(fragment_table_index[i], NULL, 92002bc3bcabf2b219f63961f07293b83629948f026plougher ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); 921545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); 92202bc3bcabf2b219f63961f07293b83629948f026plougher } 92302bc3bcabf2b219f63961f07293b83629948f026plougher 92402bc3bcabf2b219f63961f07293b83629948f026plougher if(swap) { 92502bc3bcabf2b219f63961f07293b83629948f026plougher squashfs_fragment_entry_2 sfragment; 92602bc3bcabf2b219f63961f07293b83629948f026plougher for(i = 0; i < sBlk.fragments; i++) { 92702bc3bcabf2b219f63961f07293b83629948f026plougher SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); 92802bc3bcabf2b219f63961f07293b83629948f026plougher memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); 92902bc3bcabf2b219f63961f07293b83629948f026plougher } 93002bc3bcabf2b219f63961f07293b83629948f026plougher } 93102bc3bcabf2b219f63961f07293b83629948f026plougher} 93202bc3bcabf2b219f63961f07293b83629948f026plougher 93302bc3bcabf2b219f63961f07293b83629948f026plougher 934ba3d412c7c811a9b335a52ec497ce511e35b2bc8ploughervoid read_fragment_table_1() 935ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher{ 936ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher} 937ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 938ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 9398888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid read_fragment(unsigned int fragment, long long *start_block, int *size) 940443c15812032991c98b33b5424b17bcd55fe3575plougher{ 941fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_fragment: reading fragment %d\n", fragment); 942fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 9438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; 9448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher *start_block = fragment_entry->start_block; 9458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher *size = fragment_entry->size; 946443c15812032991c98b33b5424b17bcd55fe3575plougher} 947443c15812032991c98b33b5424b17bcd55fe3575plougher 948443c15812032991c98b33b5424b17bcd55fe3575plougher 9498888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid read_fragment_2(unsigned int fragment, long long *start_block, int *size) 95002bc3bcabf2b219f63961f07293b83629948f026plougher{ 95102bc3bcabf2b219f63961f07293b83629948f026plougher TRACE("read_fragment: reading fragment %d\n", fragment); 95202bc3bcabf2b219f63961f07293b83629948f026plougher 9538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; 9548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher *start_block = fragment_entry->start_block; 9558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher *size = fragment_entry->size; 95602bc3bcabf2b219f63961f07293b83629948f026plougher} 95702bc3bcabf2b219f63961f07293b83629948f026plougher 95802bc3bcabf2b219f63961f07293b83629948f026plougher 959b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 960b9cee889506e674726856035dba52d5e1cceeb99plougherchar *zero_data; 961b9cee889506e674726856035dba52d5e1cceeb99plougher 9628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint write_block(int file_fd, char *buffer, int size, int hole) 963b9cee889506e674726856035dba52d5e1cceeb99plougher{ 964b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 965b9cee889506e674726856035dba52d5e1cceeb99plougher 966b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 967b9cee889506e674726856035dba52d5e1cceeb99plougher if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { 968b9cee889506e674726856035dba52d5e1cceeb99plougher /* failed to seek beyond end of file */ 969b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 970b9cee889506e674726856035dba52d5e1cceeb99plougher EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); 971b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 972b9cee889506e674726856035dba52d5e1cceeb99plougher lseek_broken = TRUE; 973b9cee889506e674726856035dba52d5e1cceeb99plougher } 974b9cee889506e674726856035dba52d5e1cceeb99plougher if(lseek_broken) { 975b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 976b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 977b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 978b9cee889506e674726856035dba52d5e1cceeb99plougher avail_bytes = hole > block_size ? block_size : hole; 979b9cee889506e674726856035dba52d5e1cceeb99plougher if(write(file_fd, zero_data, avail_bytes) < avail_bytes) 980b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 981b9cee889506e674726856035dba52d5e1cceeb99plougher } 982b9cee889506e674726856035dba52d5e1cceeb99plougher } 983b9cee889506e674726856035dba52d5e1cceeb99plougher } 984b9cee889506e674726856035dba52d5e1cceeb99plougher 985b9cee889506e674726856035dba52d5e1cceeb99plougher if(write(file_fd, buffer, size) < size) 986b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 987b9cee889506e674726856035dba52d5e1cceeb99plougher 988b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 989b9cee889506e674726856035dba52d5e1cceeb99plougher 990b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 991b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 992b9cee889506e674726856035dba52d5e1cceeb99plougher} 993b9cee889506e674726856035dba52d5e1cceeb99plougher 9948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 9958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct file_entry { 9968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int offset; 9978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 9988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *buffer; 9998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 10008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct squashfs_file { 10038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int fd; 10048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int blocks; 100579df93becb68081effabebba3006c794be308598plougher long long file_size; 100679df93becb68081effabebba3006c794be308598plougher int mode; 100779df93becb68081effabebba3006c794be308598plougher uid_t uid; 100879df93becb68081effabebba3006c794be308598plougher gid_t gid; 100979df93becb68081effabebba3006c794be308598plougher time_t time; 101079df93becb68081effabebba3006c794be308598plougher char *pathname; 10118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 10128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 101479df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 1015443c15812032991c98b33b5424b17bcd55fe3575plougher{ 10168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 1017f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 101879df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 101979df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 10208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file; 1021443c15812032991c98b33b5424b17bcd55fe3575plougher 102279df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 1023443c15812032991c98b33b5424b17bcd55fe3575plougher 102479df93becb68081effabebba3006c794be308598plougher if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777)) == -1) { 1025443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("write_file: failed to create file %s, because %s\n", pathname, 1026443c15812032991c98b33b5424b17bcd55fe3575plougher strerror(errno)); 1027443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1028443c15812032991c98b33b5424b17bcd55fe3575plougher } 1029443c15812032991c98b33b5424b17bcd55fe3575plougher 103079df93becb68081effabebba3006c794be308598plougher if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) 10318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 1032443c15812032991c98b33b5424b17bcd55fe3575plougher 103379df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 1034443c15812032991c98b33b5424b17bcd55fe3575plougher 10358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if((file = malloc(sizeof(struct squashfs_file))) == NULL) 10368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 1037443c15812032991c98b33b5424b17bcd55fe3575plougher 10388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* the writer thread is queued a squashfs_file structure describing the 10398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * file. If the file has one or more blocks or a fragments they are queued 10408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * separately (references to blocks in the cache). */ 10418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file->fd = file_fd; 104279df93becb68081effabebba3006c794be308598plougher file->file_size = inode->data; 104379df93becb68081effabebba3006c794be308598plougher file->mode = inode->mode; 104479df93becb68081effabebba3006c794be308598plougher file->gid = inode->gid; 104579df93becb68081effabebba3006c794be308598plougher file->uid = inode->uid; 104679df93becb68081effabebba3006c794be308598plougher file->time = inode->time; 104779df93becb68081effabebba3006c794be308598plougher file->pathname = strdup(pathname); 104879df93becb68081effabebba3006c794be308598plougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 10498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, file); 1050443c15812032991c98b33b5424b17bcd55fe3575plougher 105179df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 10528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 10538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = malloc(sizeof(struct file_entry *)); 10548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 10568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 10578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 105879df93becb68081effabebba3006c794be308598plougher block->size = i == file_end ? inode->data & (block_size - 1) : block_size; 10598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block_list[i] == 0) /* sparse file */ 10608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 10618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 10628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(data_cache, start, block_list[i]); 10638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == NULL) 10648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: cache_get failed\n"); 10658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 1066443c15812032991c98b33b5424b17bcd55fe3575plougher } 10678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1068443c15812032991c98b33b5424b17bcd55fe3575plougher } 1069443c15812032991c98b33b5424b17bcd55fe3575plougher 107079df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 10718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 10728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 10738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = malloc(sizeof(struct file_entry *)); 10748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 10768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 107779df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 10788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 10798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == NULL) 10808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: cache_get failed\n"); 108179df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 108279df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 10838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1084b9cee889506e674726856035dba52d5e1cceeb99plougher } 1085b9cee889506e674726856035dba52d5e1cceeb99plougher 1086b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 1087443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1088443c15812032991c98b33b5424b17bcd55fe3575plougher} 1089476dcb48b24efff22caa970f000e151f1b28918dplougher 1090476dcb48b24efff22caa970f000e151f1b28918dplougher 10916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherstatic struct inode *read_inode(unsigned int start_block, unsigned int offset) 1092476dcb48b24efff22caa970f000e151f1b28918dplougher{ 1093476dcb48b24efff22caa970f000e151f1b28918dplougher static squashfs_inode_header header; 1094476dcb48b24efff22caa970f000e151f1b28918dplougher long long start = sBlk.inode_table_start + start_block; 1095545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int bytes = lookup_entry(inode_table_hash, start); 1096476dcb48b24efff22caa970f000e151f1b28918dplougher char *block_ptr = inode_table + bytes + offset; 10976f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher static struct inode i; 1098476dcb48b24efff22caa970f000e151f1b28918dplougher 1099476dcb48b24efff22caa970f000e151f1b28918dplougher if(bytes == -1) 1100476dcb48b24efff22caa970f000e151f1b28918dplougher goto error; 1101476dcb48b24efff22caa970f000e151f1b28918dplougher 1102476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1103476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_base_inode_header sinode; 1104476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.base)); 1105476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); 1106476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1107476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.base, block_ptr, sizeof(header.base)); 1108476dcb48b24efff22caa970f000e151f1b28918dplougher 11096f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.uid = (uid_t) uid_table[header.base.uid]; 11106f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; 11116f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.mode = lookup_type[header.base.inode_type] | header.base.mode; 11126f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.type = header.base.inode_type; 11136f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = header.base.mtime; 11146f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.inode_number = header.base.inode_number; 1115476dcb48b24efff22caa970f000e151f1b28918dplougher 1116476dcb48b24efff22caa970f000e151f1b28918dplougher switch(header.base.inode_type) { 1117476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_DIR_TYPE: { 1118476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dir_inode_header *inode = &header.dir; 1119476dcb48b24efff22caa970f000e151f1b28918dplougher 1120476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1121476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dir_inode_header sinode; 1122476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.dir)); 1123476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); 1124476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1125476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.dir, block_ptr, sizeof(header.dir)); 1126476dcb48b24efff22caa970f000e151f1b28918dplougher 11276f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 11286f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 11296f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 11303edfa57b6a463f7d441d995559143f4861d62e98plougher break; 1131476dcb48b24efff22caa970f000e151f1b28918dplougher } 1132476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_LDIR_TYPE: { 1133476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ldir_inode_header *inode = &header.ldir; 1134476dcb48b24efff22caa970f000e151f1b28918dplougher 1135476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1136476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ldir_inode_header sinode; 1137476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.ldir)); 1138476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); 1139476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1140476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); 1141476dcb48b24efff22caa970f000e151f1b28918dplougher 11426f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 11436f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 11446f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 11453edfa57b6a463f7d441d995559143f4861d62e98plougher break; 1146476dcb48b24efff22caa970f000e151f1b28918dplougher } 1147476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FILE_TYPE: { 1148476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header *inode = &header.reg; 1149476dcb48b24efff22caa970f000e151f1b28918dplougher 1150476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1151476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header sinode; 1152476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(sinode)); 1153476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); 1154476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1155476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inode, block_ptr, sizeof(*inode)); 1156476dcb48b24efff22caa970f000e151f1b28918dplougher 11576f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 11586f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 11596f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 0 : inode->file_size % sBlk.block_size; 11606f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.fragment = inode->fragment; 11616f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 11626f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? 11636f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher (inode->file_size + sBlk.block_size - 1) >> 11646f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sBlk.block_log : inode->file_size >> sBlk.block_log; 11656f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 11666f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.block_ptr = block_ptr + sizeof(*inode); 1167476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1168476dcb48b24efff22caa970f000e151f1b28918dplougher } 1169476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_LREG_TYPE: { 1170476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_lreg_inode_header *inode = &header.lreg; 1171476dcb48b24efff22caa970f000e151f1b28918dplougher 1172476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1173476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_lreg_inode_header sinode; 1174476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(sinode)); 1175476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); 1176476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1177476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inode, block_ptr, sizeof(*inode)); 1178476dcb48b24efff22caa970f000e151f1b28918dplougher 11796f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 11806f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 11816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 0 : inode->file_size % sBlk.block_size; 11826f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.fragment = inode->fragment; 11836f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 11846f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? 11856f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher (inode->file_size + sBlk.block_size - 1) >> 11866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sBlk.block_log : inode->file_size >> sBlk.block_log; 11876f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 11886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.block_ptr = block_ptr + sizeof(*inode); 1189476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1190476dcb48b24efff22caa970f000e151f1b28918dplougher } 1191476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SYMLINK_TYPE: { 1192476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header *inodep = &header.symlink; 1193476dcb48b24efff22caa970f000e151f1b28918dplougher 1194476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1195476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header sinodep; 1196476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1197476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); 1198476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1199476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1200476dcb48b24efff22caa970f000e151f1b28918dplougher 12016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); 12026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.symlink[inodep->symlink_size] = '\0'; 12036f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->symlink_size; 1204476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1205476dcb48b24efff22caa970f000e151f1b28918dplougher } 1206476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_BLKDEV_TYPE: 1207476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_CHRDEV_TYPE: { 1208476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header *inodep = &header.dev; 1209476dcb48b24efff22caa970f000e151f1b28918dplougher 1210476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1211476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header sinodep; 1212476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1213476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); 1214476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1215476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1216476dcb48b24efff22caa970f000e151f1b28918dplougher 12176f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->rdev; 1218476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1219476dcb48b24efff22caa970f000e151f1b28918dplougher } 1220476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FIFO_TYPE: 1221476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SOCKET_TYPE: 12226f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = 0; 1223476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1224476dcb48b24efff22caa970f000e151f1b28918dplougher default: 12256f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); 1226476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1227476dcb48b24efff22caa970f000e151f1b28918dplougher } 12286f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher return &i; 1229476dcb48b24efff22caa970f000e151f1b28918dplougher 1230476dcb48b24efff22caa970f000e151f1b28918dploughererror: 1231476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1232476dcb48b24efff22caa970f000e151f1b28918dplougher} 1233476dcb48b24efff22caa970f000e151f1b28918dplougher 1234443c15812032991c98b33b5424b17bcd55fe3575plougher 12356f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 1236443c15812032991c98b33b5424b17bcd55fe3575plougher{ 12376f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 1238443c15812032991c98b33b5424b17bcd55fe3575plougher 12396f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 1240443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 12416013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 12426013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 12436013a30bd39550decc2546a47e5168e57bfcfde8plougher 12446f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 1245443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); 1246443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1247443c15812032991c98b33b5424b17bcd55fe3575plougher } 1248443c15812032991c98b33b5424b17bcd55fe3575plougher 1249443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1250443c15812032991c98b33b5424b17bcd55fe3575plougher } 1251443c15812032991c98b33b5424b17bcd55fe3575plougher 12526f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 12536f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 12546f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 12556f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); 1256443c15812032991c98b33b5424b17bcd55fe3575plougher 125779df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 1258443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 1259443c15812032991c98b33b5424b17bcd55fe3575plougher break; 12606f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 1261545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: symlink, symlink_size %lld\n", i->data); 1262443c15812032991c98b33b5424b17bcd55fe3575plougher 1263a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1264a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1265a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 12666f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 1267443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, 1268443c15812032991c98b33b5424b17bcd55fe3575plougher strerror(errno)); 1269443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1270443c15812032991c98b33b5424b17bcd55fe3575plougher } 1271443c15812032991c98b33b5424b17bcd55fe3575plougher 12729dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 12736f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 1274443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); 1275443c15812032991c98b33b5424b17bcd55fe3575plougher } 1276443c15812032991c98b33b5424b17bcd55fe3575plougher 1277443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 1278443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1279443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 1280443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_CHRDEV_TYPE: { 12816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 1282545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 1283443c15812032991c98b33b5424b17bcd55fe3575plougher 12849dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 1285a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1286a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1287a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 12886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 12896f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { 1290443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create %s device %s, because %s\n", 12916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher chrdev ? "character" : "block", pathname, strerror(errno)); 1292443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1293443c15812032991c98b33b5424b17bcd55fe3575plougher } 12946f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); 1295443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 1296443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1297443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", 1298545404219cdd79c1e06ac7d0698d02a15240c4c3plougher chrdev ? "character" : "block", pathname); 1299443c15812032991c98b33b5424b17bcd55fe3575plougher break; 13006f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1301443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 1302443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 1303443c15812032991c98b33b5424b17bcd55fe3575plougher 1304a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1305a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1306a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 1307443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 1308443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: failed to create fifo %s, because %s\n", 1309443c15812032991c98b33b5424b17bcd55fe3575plougher pathname, strerror(errno)); 1310443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1311443c15812032991c98b33b5424b17bcd55fe3575plougher } 13126f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); 1313443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 1314443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1315443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 1316443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 1317443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 1318443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1319443c15812032991c98b33b5424b17bcd55fe3575plougher default: 13206f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("Unknown inode type %d in create_inode_table!\n", i->type); 1321443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1322443c15812032991c98b33b5424b17bcd55fe3575plougher } 1323fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 13246f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 1325443c15812032991c98b33b5424b17bcd55fe3575plougher 1326443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1327443c15812032991c98b33b5424b17bcd55fe3575plougher} 1328443c15812032991c98b33b5424b17bcd55fe3575plougher 1329443c15812032991c98b33b5424b17bcd55fe3575plougher 13306f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherstruct inode *read_inode_2(unsigned int start_block, unsigned int offset) 1331476dcb48b24efff22caa970f000e151f1b28918dplougher{ 1332476dcb48b24efff22caa970f000e151f1b28918dplougher static squashfs_inode_header_2 header; 1333476dcb48b24efff22caa970f000e151f1b28918dplougher long long start = sBlk.inode_table_start + start_block; 1334545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int bytes = lookup_entry(inode_table_hash, start); 1335476dcb48b24efff22caa970f000e151f1b28918dplougher char *block_ptr = inode_table + bytes + offset; 13366f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher static struct inode i; 13376f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher static int inode_number = 1; 1338476dcb48b24efff22caa970f000e151f1b28918dplougher 1339476dcb48b24efff22caa970f000e151f1b28918dplougher if(bytes == -1) 1340476dcb48b24efff22caa970f000e151f1b28918dplougher goto error; 1341476dcb48b24efff22caa970f000e151f1b28918dplougher 1342476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1343476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_base_inode_header_2 sinode; 1344476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.base)); 1345476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); 1346476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1347476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.base, block_ptr, sizeof(header.base)); 1348476dcb48b24efff22caa970f000e151f1b28918dplougher 13496f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.uid = (uid_t) uid_table[header.base.uid]; 13506f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; 13516f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.mode = lookup_type[header.base.inode_type] | header.base.mode; 13526f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.type = header.base.inode_type; 13536f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = sBlk.mkfs_time; 13546f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.inode_number = inode_number++; 1355476dcb48b24efff22caa970f000e151f1b28918dplougher 1356476dcb48b24efff22caa970f000e151f1b28918dplougher switch(header.base.inode_type) { 1357476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_DIR_TYPE: { 1358476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dir_inode_header_2 *inode = &header.dir; 1359476dcb48b24efff22caa970f000e151f1b28918dplougher 1360476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1361476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dir_inode_header sinode; 1362476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.dir)); 1363476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); 1364476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1365476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.dir, block_ptr, sizeof(header.dir)); 1366476dcb48b24efff22caa970f000e151f1b28918dplougher 13676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 13686f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 13696f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 13706f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = inode->mtime; 13713edfa57b6a463f7d441d995559143f4861d62e98plougher break; 1372476dcb48b24efff22caa970f000e151f1b28918dplougher } 1373476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_LDIR_TYPE: { 1374476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ldir_inode_header_2 *inode = &header.ldir; 1375476dcb48b24efff22caa970f000e151f1b28918dplougher 1376476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1377476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ldir_inode_header sinode; 1378476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.ldir)); 1379476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); 1380476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1381476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); 1382476dcb48b24efff22caa970f000e151f1b28918dplougher 13836f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 13846f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 13856f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 13866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = inode->mtime; 13873edfa57b6a463f7d441d995559143f4861d62e98plougher break; 1388476dcb48b24efff22caa970f000e151f1b28918dplougher } 1389476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FILE_TYPE: { 1390476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header_2 *inode = &header.reg; 1391476dcb48b24efff22caa970f000e151f1b28918dplougher 1392476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1393476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header_2 sinode; 1394476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(sinode)); 1395476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); 1396476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1397476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inode, block_ptr, sizeof(*inode)); 1398476dcb48b24efff22caa970f000e151f1b28918dplougher 13996f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 14006f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = inode->mtime; 14016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 14026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 0 : inode->file_size % sBlk.block_size; 14036f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.fragment = inode->fragment; 14046f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = inode->offset; 14056f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? 14066f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher (inode->file_size + sBlk.block_size - 1) >> 14076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sBlk.block_log : inode->file_size >> sBlk.block_log; 14086f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 14096f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.block_ptr = block_ptr + sizeof(*inode); 1410476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1411476dcb48b24efff22caa970f000e151f1b28918dplougher } 1412476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SYMLINK_TYPE: { 1413476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header_2 *inodep = &header.symlink; 1414476dcb48b24efff22caa970f000e151f1b28918dplougher 1415476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1416476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header_2 sinodep; 1417476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1418476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); 1419476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1420476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1421476dcb48b24efff22caa970f000e151f1b28918dplougher 14226f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); 14236f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.symlink[inodep->symlink_size] = '\0'; 14246f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->symlink_size; 1425476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1426476dcb48b24efff22caa970f000e151f1b28918dplougher } 1427476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_BLKDEV_TYPE: 1428476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_CHRDEV_TYPE: { 1429476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header_2 *inodep = &header.dev; 1430476dcb48b24efff22caa970f000e151f1b28918dplougher 1431476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1432476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header_2 sinodep; 1433476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1434476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); 1435476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1436476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1437476dcb48b24efff22caa970f000e151f1b28918dplougher 14386f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->rdev; 1439476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1440476dcb48b24efff22caa970f000e151f1b28918dplougher } 1441476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FIFO_TYPE: 1442476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SOCKET_TYPE: 14436f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = 0; 1444476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1445476dcb48b24efff22caa970f000e151f1b28918dplougher default: 1446476dcb48b24efff22caa970f000e151f1b28918dplougher ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); 1447476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1448476dcb48b24efff22caa970f000e151f1b28918dplougher } 14496f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher return &i; 1450476dcb48b24efff22caa970f000e151f1b28918dplougher 1451476dcb48b24efff22caa970f000e151f1b28918dploughererror: 1452476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1453476dcb48b24efff22caa970f000e151f1b28918dplougher} 1454476dcb48b24efff22caa970f000e151f1b28918dplougher 1455476dcb48b24efff22caa970f000e151f1b28918dplougher 14566f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherstruct inode *read_inode_1(unsigned int start_block, unsigned int offset) 1457476dcb48b24efff22caa970f000e151f1b28918dplougher{ 1458476dcb48b24efff22caa970f000e151f1b28918dplougher static squashfs_inode_header_1 header; 1459476dcb48b24efff22caa970f000e151f1b28918dplougher long long start = sBlk.inode_table_start + start_block; 1460545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int bytes = lookup_entry(inode_table_hash, start); 1461476dcb48b24efff22caa970f000e151f1b28918dplougher char *block_ptr = inode_table + bytes + offset; 14626f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher static struct inode i; 14636f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher static int inode_number = 1; 1464476dcb48b24efff22caa970f000e151f1b28918dplougher 1465476dcb48b24efff22caa970f000e151f1b28918dplougher if(bytes == -1) 1466476dcb48b24efff22caa970f000e151f1b28918dplougher goto error; 1467476dcb48b24efff22caa970f000e151f1b28918dplougher 1468476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1469476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_base_inode_header_1 sinode; 1470476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(header.base)); 1471476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); 1472476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1473476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&header.base, block_ptr, sizeof(header.base)); 1474476dcb48b24efff22caa970f000e151f1b28918dplougher 14756f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; 1476476dcb48b24efff22caa970f000e151f1b28918dplougher if(header.base.inode_type == SQUASHFS_IPC_TYPE) { 1477476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ipc_inode_header_1 *inodep = &header.ipc; 1478476dcb48b24efff22caa970f000e151f1b28918dplougher 1479476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1480476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_ipc_inode_header_1 sinodep; 1481476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1482476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); 1483476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1484476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1485476dcb48b24efff22caa970f000e151f1b28918dplougher 1486476dcb48b24efff22caa970f000e151f1b28918dplougher if(inodep->type == SQUASHFS_SOCKET_TYPE) { 14876f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.mode = S_IFSOCK | header.base.mode; 14886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.type = SQUASHFS_SOCKET_TYPE; 148988facddfd83e48a907b82210ddccbb4f84d80aecplougher } else { 14906f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.mode = S_IFIFO | header.base.mode; 14916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.type = SQUASHFS_FIFO_TYPE; 1492476dcb48b24efff22caa970f000e151f1b28918dplougher } 14936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; 1494476dcb48b24efff22caa970f000e151f1b28918dplougher } else { 14956f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; 14966f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; 1497476dcb48b24efff22caa970f000e151f1b28918dplougher } 14986f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; 14996f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = sBlk.mkfs_time; 15006f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.inode_number = inode_number ++; 1501476dcb48b24efff22caa970f000e151f1b28918dplougher 15026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i.type) { 150388facddfd83e48a907b82210ddccbb4f84d80aecplougher case SQUASHFS_DIR_TYPE: { 150488facddfd83e48a907b82210ddccbb4f84d80aecplougher squashfs_dir_inode_header_1 *inode = &header.dir; 15056f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 150688facddfd83e48a907b82210ddccbb4f84d80aecplougher if(swap) { 150788facddfd83e48a907b82210ddccbb4f84d80aecplougher squashfs_dir_inode_header_1 sinode; 150888facddfd83e48a907b82210ddccbb4f84d80aecplougher memcpy(&sinode, block_ptr, sizeof(header.dir)); 150988facddfd83e48a907b82210ddccbb4f84d80aecplougher SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); 151088facddfd83e48a907b82210ddccbb4f84d80aecplougher } else 1511e05e7ae96eb9af6bb7e46c52f55b12469c24c7d9plougher memcpy(inode, block_ptr, sizeof(header.dir)); 151288facddfd83e48a907b82210ddccbb4f84d80aecplougher 15136f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 15146f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 15156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = inode->mtime; 1516e05e7ae96eb9af6bb7e46c52f55b12469c24c7d9plougher break; 151788facddfd83e48a907b82210ddccbb4f84d80aecplougher } 1518476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FILE_TYPE: { 1519476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header_1 *inode = &header.reg; 1520476dcb48b24efff22caa970f000e151f1b28918dplougher 1521476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1522476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_reg_inode_header_1 sinode; 1523476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinode, block_ptr, sizeof(sinode)); 1524476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); 1525476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1526476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inode, block_ptr, sizeof(*inode)); 1527476dcb48b24efff22caa970f000e151f1b28918dplougher 15286f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inode->file_size; 15296f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.time = inode->mtime; 15306f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.blocks = (inode->file_size + sBlk.block_size - 1) >> 15316f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sBlk.block_log; 15326f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.start = inode->start_block; 15336f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.block_ptr = block_ptr + sizeof(*inode); 15346f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.fragment = 0; 15356f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.frag_bytes = 0; 15366f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.offset = 0; 1537e05e7ae96eb9af6bb7e46c52f55b12469c24c7d9plougher break; 1538476dcb48b24efff22caa970f000e151f1b28918dplougher } 1539476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SYMLINK_TYPE: { 1540476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header_1 *inodep = &header.symlink; 1541476dcb48b24efff22caa970f000e151f1b28918dplougher 1542476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1543476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_symlink_inode_header_1 sinodep; 1544476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1545476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); 1546476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1547476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1548476dcb48b24efff22caa970f000e151f1b28918dplougher 15496f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); 15506f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.symlink[inodep->symlink_size] = '\0'; 15516f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->symlink_size; 1552476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1553476dcb48b24efff22caa970f000e151f1b28918dplougher } 1554476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_BLKDEV_TYPE: 1555476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_CHRDEV_TYPE: { 1556476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header_1 *inodep = &header.dev; 1557476dcb48b24efff22caa970f000e151f1b28918dplougher 1558476dcb48b24efff22caa970f000e151f1b28918dplougher if(swap) { 1559476dcb48b24efff22caa970f000e151f1b28918dplougher squashfs_dev_inode_header_1 sinodep; 1560476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(&sinodep, block_ptr, sizeof(sinodep)); 1561476dcb48b24efff22caa970f000e151f1b28918dplougher SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); 1562476dcb48b24efff22caa970f000e151f1b28918dplougher } else 1563476dcb48b24efff22caa970f000e151f1b28918dplougher memcpy(inodep, block_ptr, sizeof(*inodep)); 1564476dcb48b24efff22caa970f000e151f1b28918dplougher 15656f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = inodep->rdev; 1566476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1567476dcb48b24efff22caa970f000e151f1b28918dplougher } 1568476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_FIFO_TYPE: 1569476dcb48b24efff22caa970f000e151f1b28918dplougher case SQUASHFS_SOCKET_TYPE: { 15706f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher i.data = 0; 1571476dcb48b24efff22caa970f000e151f1b28918dplougher break; 1572476dcb48b24efff22caa970f000e151f1b28918dplougher } 1573476dcb48b24efff22caa970f000e151f1b28918dplougher default: 1574476dcb48b24efff22caa970f000e151f1b28918dplougher ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); 1575476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1576476dcb48b24efff22caa970f000e151f1b28918dplougher } 15776f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher return &i; 1578476dcb48b24efff22caa970f000e151f1b28918dplougher 1579476dcb48b24efff22caa970f000e151f1b28918dploughererror: 1580476dcb48b24efff22caa970f000e151f1b28918dplougher return NULL; 1581476dcb48b24efff22caa970f000e151f1b28918dplougher} 1582476dcb48b24efff22caa970f000e151f1b28918dplougher 1583476dcb48b24efff22caa970f000e151f1b28918dplougher 158402bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_directory_table(long long start, long long end) 1585443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1586443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 1587443c15812032991c98b33b5424b17bcd55fe3575plougher 1588443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 15899dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = 15909dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher realloc(directory_table, size += 15919dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher SQUASHFS_METADATA_SIZE)) == NULL) 1592443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); 1593443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_directory_table: reading block 0x%llx\n", start); 1594443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 159502bc3bcabf2b219f63961f07293b83629948f026plougher if((res = read_block(start, &start, directory_table + bytes)) == 0) 1596443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); 1597443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 1598443c15812032991c98b33b5424b17bcd55fe3575plougher } 1599443c15812032991c98b33b5424b17bcd55fe3575plougher} 1600443c15812032991c98b33b5424b17bcd55fe3575plougher 1601443c15812032991c98b33b5424b17bcd55fe3575plougher 1602443c15812032991c98b33b5424b17bcd55fe3575plougher#define DIR_ENT_SIZE 16 1603443c15812032991c98b33b5424b17bcd55fe3575plougher 1604443c15812032991c98b33b5424b17bcd55fe3575plougherstruct dir_ent { 1605443c15812032991c98b33b5424b17bcd55fe3575plougher char name[SQUASHFS_NAME_LEN + 1]; 1606443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int start_block; 1607443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int offset; 1608443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1609443c15812032991c98b33b5424b17bcd55fe3575plougher}; 1610443c15812032991c98b33b5424b17bcd55fe3575plougher 1611443c15812032991c98b33b5424b17bcd55fe3575plougherstruct dir { 1612443c15812032991c98b33b5424b17bcd55fe3575plougher int dir_count; 1613443c15812032991c98b33b5424b17bcd55fe3575plougher int cur_entry; 1614443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int mode; 16156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher uid_t uid; 16166f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher gid_t guid; 1617443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int mtime; 1618443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir_ent *dirs; 1619443c15812032991c98b33b5424b17bcd55fe3575plougher}; 1620443c15812032991c98b33b5424b17bcd55fe3575plougher 1621443c15812032991c98b33b5424b17bcd55fe3575plougher 1622eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherstruct dir *squashfs_opendir(unsigned int block_start, unsigned int offset, struct inode **i) 1623443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1624443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_header dirh; 1625443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; 1626443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; 16276f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher long long start; 16286f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int bytes; 1629443c15812032991c98b33b5424b17bcd55fe3575plougher int dir_count, size; 1630443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir_ent *new_dir; 1631443c15812032991c98b33b5424b17bcd55fe3575plougher struct dir *dir; 1632443c15812032991c98b33b5424b17bcd55fe3575plougher 1633fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); 1634443c15812032991c98b33b5424b17bcd55fe3575plougher 1635eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if((*i = s_ops.read_inode(block_start, offset)) == NULL) { 16366f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); 1637443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 1638443c15812032991c98b33b5424b17bcd55fe3575plougher } 1639443c15812032991c98b33b5424b17bcd55fe3575plougher 1640eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher start = sBlk.directory_table_start + (*i)->start; 1641443c15812032991c98b33b5424b17bcd55fe3575plougher bytes = lookup_entry(directory_table_hash, start); 1642443c15812032991c98b33b5424b17bcd55fe3575plougher 1643443c15812032991c98b33b5424b17bcd55fe3575plougher if(bytes == -1) { 1644fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("squashfs_opendir: directory block %d not found!\n", block_start); 1645443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 1646443c15812032991c98b33b5424b17bcd55fe3575plougher } 16476f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1648eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher bytes += (*i)->offset; 1649eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher size = (*i)->data + bytes - 3; 1650443c15812032991c98b33b5424b17bcd55fe3575plougher 1651443c15812032991c98b33b5424b17bcd55fe3575plougher if((dir = malloc(sizeof(struct dir))) == NULL) { 1652443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("squashfs_opendir: malloc failed!\n"); 1653443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 1654443c15812032991c98b33b5424b17bcd55fe3575plougher } 1655443c15812032991c98b33b5424b17bcd55fe3575plougher 1656443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dir_count = 0; 1657443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry = 0; 1658eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->mode = (*i)->mode; 1659eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->uid = (*i)->uid; 1660eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->guid = (*i)->gid; 1661eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->mtime = (*i)->time; 1662443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs = NULL; 1663443c15812032991c98b33b5424b17bcd55fe3575plougher 1664fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher while(bytes < size) { 1665443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 1666443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_header sdirh; 1667443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); 1668443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 1669443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1670443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&dirh, directory_table + bytes, sizeof(dirh)); 1671fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1672443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count = dirh.count + 1; 1673fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); 1674443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += sizeof(dirh); 1675443c15812032991c98b33b5424b17bcd55fe3575plougher 1676443c15812032991c98b33b5424b17bcd55fe3575plougher while(dir_count--) { 1677443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 1678443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_dir_entry sdire; 1679443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(&sdire, directory_table + bytes, sizeof(sdire)); 1680443c15812032991c98b33b5424b17bcd55fe3575plougher SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 1681443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1682443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(dire, directory_table + bytes, sizeof(dire)); 1683443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += sizeof(*dire); 1684443c15812032991c98b33b5424b17bcd55fe3575plougher 1685443c15812032991c98b33b5424b17bcd55fe3575plougher memcpy(dire->name, directory_table + bytes, dire->size + 1); 1686443c15812032991c98b33b5424b17bcd55fe3575plougher dire->name[dire->size + 1] = '\0'; 1687fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); 1688443c15812032991c98b33b5424b17bcd55fe3575plougher if((dir->dir_count % DIR_ENT_SIZE) == 0) { 1689443c15812032991c98b33b5424b17bcd55fe3575plougher if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { 1690443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("squashfs_opendir: realloc failed!\n"); 1691443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1692443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1693443c15812032991c98b33b5424b17bcd55fe3575plougher return NULL; 1694443c15812032991c98b33b5424b17bcd55fe3575plougher } 1695443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs = new_dir; 1696443c15812032991c98b33b5424b17bcd55fe3575plougher } 1697443c15812032991c98b33b5424b17bcd55fe3575plougher strcpy(dir->dirs[dir->dir_count].name, dire->name); 1698443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].start_block = dirh.start_block; 1699443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].offset = dire->offset; 1700443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dirs[dir->dir_count].type = dire->type; 1701443c15812032991c98b33b5424b17bcd55fe3575plougher dir->dir_count ++; 1702443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += dire->size + 1; 1703443c15812032991c98b33b5424b17bcd55fe3575plougher } 1704443c15812032991c98b33b5424b17bcd55fe3575plougher } 1705443c15812032991c98b33b5424b17bcd55fe3575plougher 1706443c15812032991c98b33b5424b17bcd55fe3575plougher return dir; 1707443c15812032991c98b33b5424b17bcd55fe3575plougher} 1708443c15812032991c98b33b5424b17bcd55fe3575plougher 1709443c15812032991c98b33b5424b17bcd55fe3575plougher 1710eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherstruct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset, struct inode **i) 171102bc3bcabf2b219f63961f07293b83629948f026plougher{ 171202bc3bcabf2b219f63961f07293b83629948f026plougher squashfs_dir_header_2 dirh; 171302bc3bcabf2b219f63961f07293b83629948f026plougher char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; 171402bc3bcabf2b219f63961f07293b83629948f026plougher squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; 17156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher long long start; 17166f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int bytes; 171702bc3bcabf2b219f63961f07293b83629948f026plougher int dir_count, size; 171802bc3bcabf2b219f63961f07293b83629948f026plougher struct dir_ent *new_dir; 171902bc3bcabf2b219f63961f07293b83629948f026plougher struct dir *dir; 172002bc3bcabf2b219f63961f07293b83629948f026plougher 172102bc3bcabf2b219f63961f07293b83629948f026plougher TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); 172202bc3bcabf2b219f63961f07293b83629948f026plougher 1723eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(((*i) = s_ops.read_inode(block_start, offset)) == NULL) { 17246f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); 172502bc3bcabf2b219f63961f07293b83629948f026plougher return NULL; 172602bc3bcabf2b219f63961f07293b83629948f026plougher } 172702bc3bcabf2b219f63961f07293b83629948f026plougher 1728eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher start = sBlk.directory_table_start + (*i)->start; 172902bc3bcabf2b219f63961f07293b83629948f026plougher bytes = lookup_entry(directory_table_hash, start); 173002bc3bcabf2b219f63961f07293b83629948f026plougher 173102bc3bcabf2b219f63961f07293b83629948f026plougher if(bytes == -1) { 173202bc3bcabf2b219f63961f07293b83629948f026plougher ERROR("squashfs_opendir: directory block %d not found!\n", block_start); 173302bc3bcabf2b219f63961f07293b83629948f026plougher return NULL; 173402bc3bcabf2b219f63961f07293b83629948f026plougher } 1735ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1736eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher bytes += (*i)->offset; 1737eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher size = (*i)->data + bytes; 1738ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1739ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if((dir = malloc(sizeof(struct dir))) == NULL) { 1740ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher ERROR("squashfs_opendir: malloc failed!\n"); 1741ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher return NULL; 1742ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 1743ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1744ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dir_count = 0; 1745ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->cur_entry = 0; 1746eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->mode = (*i)->mode; 1747eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->uid = (*i)->uid; 1748eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->guid = (*i)->gid; 1749eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher dir->mtime = (*i)->time; 1750ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dirs = NULL; 1751ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1752ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher while(bytes < size) { 1753ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(swap) { 1754ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher squashfs_dir_header_2 sdirh; 1755ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); 1756ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); 1757ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else 1758ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(&dirh, directory_table + bytes, sizeof(dirh)); 1759ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1760ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir_count = dirh.count + 1; 1761ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); 1762ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher bytes += sizeof(dirh); 1763ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1764ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher while(dir_count--) { 1765ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(swap) { 1766ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher squashfs_dir_entry_2 sdire; 1767ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(&sdire, directory_table + bytes, sizeof(sdire)); 1768ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); 1769ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else 1770ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(dire, directory_table + bytes, sizeof(dire)); 1771ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher bytes += sizeof(*dire); 1772ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1773ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher memcpy(dire->name, directory_table + bytes, dire->size + 1); 1774ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dire->name[dire->size + 1] = '\0'; 1775ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); 1776ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if((dir->dir_count % DIR_ENT_SIZE) == 0) { 1777ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { 1778ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher ERROR("squashfs_opendir: realloc failed!\n"); 1779ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher free(dir->dirs); 1780ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher free(dir); 1781ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher return NULL; 1782ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 1783ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dirs = new_dir; 1784ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 1785ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher strcpy(dir->dirs[dir->dir_count].name, dire->name); 1786ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dirs[dir->dir_count].start_block = dirh.start_block; 1787ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dirs[dir->dir_count].offset = dire->offset; 1788ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dirs[dir->dir_count].type = dire->type; 1789ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher dir->dir_count ++; 1790ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher bytes += dire->size + 1; 1791ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 1792ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 1793ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1794ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher return dir; 1795ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher} 1796ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 1797ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 17989dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 17999dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1800443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1801443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1802443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1803443c15812032991c98b33b5424b17bcd55fe3575plougher 1804443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1805443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1806443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1807443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1808443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1809443c15812032991c98b33b5424b17bcd55fe3575plougher 1810443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1811443c15812032991c98b33b5424b17bcd55fe3575plougher} 1812443c15812032991c98b33b5424b17bcd55fe3575plougher 1813443c15812032991c98b33b5424b17bcd55fe3575plougher 1814443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1815443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1816443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1817443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1818443c15812032991c98b33b5424b17bcd55fe3575plougher} 1819443c15812032991c98b33b5424b17bcd55fe3575plougher 1820443c15812032991c98b33b5424b17bcd55fe3575plougher 1821b54566f5c433764830c29c83151691d0034de094plougherchar *get_component(char *target, char *targname) 1822b54566f5c433764830c29c83151691d0034de094plougher{ 1823b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 18243cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1825b54566f5c433764830c29c83151691d0034de094plougher 1826b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 1827b54566f5c433764830c29c83151691d0034de094plougher *targname ++ = *target ++; 1828b54566f5c433764830c29c83151691d0034de094plougher 1829b54566f5c433764830c29c83151691d0034de094plougher *targname = '\0'; 1830b54566f5c433764830c29c83151691d0034de094plougher 1831b54566f5c433764830c29c83151691d0034de094plougher return target; 1832b54566f5c433764830c29c83151691d0034de094plougher} 1833b54566f5c433764830c29c83151691d0034de094plougher 1834b54566f5c433764830c29c83151691d0034de094plougher 183571add234b27054974d5e29f95b3fab3072792a62plougherstruct path_entry { 183671add234b27054974d5e29f95b3fab3072792a62plougher char *name; 18374dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regex_t *preg; 183871add234b27054974d5e29f95b3fab3072792a62plougher struct pathname *paths; 183971add234b27054974d5e29f95b3fab3072792a62plougher}; 184071add234b27054974d5e29f95b3fab3072792a62plougher 184171add234b27054974d5e29f95b3fab3072792a62plougherstruct pathname { 184271add234b27054974d5e29f95b3fab3072792a62plougher int names; 184371add234b27054974d5e29f95b3fab3072792a62plougher struct path_entry *name; 184471add234b27054974d5e29f95b3fab3072792a62plougher}; 184571add234b27054974d5e29f95b3fab3072792a62plougher 1846a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames { 1847a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int count; 1848a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path[0]; 1849a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher}; 1850a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher#define PATHS_ALLOC_SIZE 10 185171add234b27054974d5e29f95b3fab3072792a62plougher 18526ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 18536ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 18546ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 18556ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 18566ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 18576ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 18586ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 18596ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 18606ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 18616ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 18626ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 18636ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 18646ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 18656ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 18666ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 18676ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 18686ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 18696ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 18704dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1871b54566f5c433764830c29c83151691d0034de094plougher{ 187271add234b27054974d5e29f95b3fab3072792a62plougher char targname[1024]; 18734dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 187471add234b27054974d5e29f95b3fab3072792a62plougher 187571add234b27054974d5e29f95b3fab3072792a62plougher target = get_component(target, targname); 187671add234b27054974d5e29f95b3fab3072792a62plougher 187771add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 18784dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if((paths = malloc(sizeof(struct pathname))) == NULL) 18794dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 18804dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 188171add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 188271add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 188371add234b27054974d5e29f95b3fab3072792a62plougher } 188471add234b27054974d5e29f95b3fab3072792a62plougher 188571add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 188671add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 188771add234b27054974d5e29f95b3fab3072792a62plougher break; 188871add234b27054974d5e29f95b3fab3072792a62plougher 18896ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 18906ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* allocate new name entry */ 189171add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 189271add234b27054974d5e29f95b3fab3072792a62plougher paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); 189371add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].name = strdup(targname); 18946ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 18954dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 18964dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 1897545404219cdd79c1e06ac7d0698d02a15240c4c3plougher error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); 1898545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 18994dba330d7b952f2f044d38e342e2ae3ea78910d6plougher char str[1024]; 19004dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 19014dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 19024dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); 19034dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 19044dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 19054dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 19066ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 19076ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 19086ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* at leaf pathname component */ 190971add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 191071add234b27054974d5e29f95b3fab3072792a62plougher else 19116ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* recurse adding child components */ 19124dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 19136ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 19146ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* existing matching entry */ 19156ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 19166ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* No sub-directory which means this is the leaf component of a 19176ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher pre-existing extract which subsumes the extract currently 19186ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher being added, in which case stop adding components */ 19196ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 19206ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* at leaf pathname component and child components exist from more 19216ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher specific extracts, delete as they're subsumed by this extract 19226ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher */ 19236ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 19246ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 19256ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 19266ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher /* recurse adding child components */ 19276ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 192871add234b27054974d5e29f95b3fab3072792a62plougher } 192971add234b27054974d5e29f95b3fab3072792a62plougher 193071add234b27054974d5e29f95b3fab3072792a62plougher return paths; 193171add234b27054974d5e29f95b3fab3072792a62plougher} 19326ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 19336ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1934a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 193571add234b27054974d5e29f95b3fab3072792a62plougher{ 1936a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new = malloc(sizeof(struct pathnames *)); 1937a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1938a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1939a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1940a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1941a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1942a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1943a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1944a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(paths->count % PATHS_ALLOC_SIZE == 0) 1945a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); 1946a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1947a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1948a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1949a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1950a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1951a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1952a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1953a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1954a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1955a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1956a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1957a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1958a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1959a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1960a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 196171add234b27054974d5e29f95b3fab3072792a62plougher 196271add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 196371add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1964b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 196571add234b27054974d5e29f95b3fab3072792a62plougher } 196671add234b27054974d5e29f95b3fab3072792a62plougher 1967a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1968a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1969a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1970a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1971a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1972a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1973a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : 1974a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; 1975a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1976a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher /* match on a leaf component, any subdirectories will 1977a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher * implicitly match, therefore return an empty new search set */ 1978a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1979a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1980a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1981a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher /* match on a non-leaf component, add any subdirectories to 1982a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher * the new set of subdirectories to scan for this name */ 1983a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1984a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1985a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1986b54566f5c433764830c29c83151691d0034de094plougher 1987a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1988a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher /* no matching names found, delete empty search set, and return 1989a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher * FALSE */ 1990a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1991a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1992a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1993a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1994a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1995a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher /* one or more matches with sub-directories found (no leaf matches), 1996a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher * return new search set and return TRUE */ 1997a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1998a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1999a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 2000a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher /* found matching leaf exclude, return empty search set and return TRUE */ 2001a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 2002a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 2003a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 2004b54566f5c433764830c29c83151691d0034de094plougher} 2005b54566f5c433764830c29c83151691d0034de094plougher 2006b54566f5c433764830c29c83151691d0034de094plougher 2007eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) 2008eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2009eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 2010eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char *name, pathname[1024]; 2011eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 2012eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 2013eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 2014eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2015eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(dir == NULL) { 2016eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); 2017eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return FALSE; 2018eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2019eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2020eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 2021eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 2022eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2023eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); 2024eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2025eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 2026eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 2027eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2028eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 2029eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2030eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 2031eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 2032eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 2033eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { 2034eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if((i = s_ops.read_inode(start_block, offset)) == NULL) { 2035eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher ERROR("failed to read header\n"); 2036eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 2037eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2038eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 2039eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher created_inode[i->inode_number - 1] = (char *) i; 2040eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_blocks += (i->data + (block_size - 1)) >> block_log; 2041eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2042eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 2043eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2044eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 2045eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2046eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2047eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 2048eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2049eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2050eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 2051eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2052eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return TRUE; 2053eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2054eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2055eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2056a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) 2057443c15812032991c98b33b5424b17bcd55fe3575plougher{ 2058443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 2059443c15812032991c98b33b5424b17bcd55fe3575plougher char *name, pathname[1024]; 2060a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 2061eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 2062eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 2063443c15812032991c98b33b5424b17bcd55fe3575plougher 2064443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir == NULL) { 2065fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); 2066443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 2067443c15812032991c98b33b5424b17bcd55fe3575plougher } 2068443c15812032991c98b33b5424b17bcd55fe3575plougher 2069eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 2070eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 2071eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2072a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { 2073443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); 2074443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 2075443c15812032991c98b33b5424b17bcd55fe3575plougher } 2076443c15812032991c98b33b5424b17bcd55fe3575plougher 2077443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 20786f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); 2079b54566f5c433764830c29c83151691d0034de094plougher 208071add234b27054974d5e29f95b3fab3072792a62plougher 208171add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 2082b54566f5c433764830c29c83151691d0034de094plougher continue; 2083b54566f5c433764830c29c83151691d0034de094plougher 2084443c15812032991c98b33b5424b17bcd55fe3575plougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 2085fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 2086443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 208771add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 2088a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher else if(new == NULL) { 20896f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((i = s_ops.read_inode(start_block, offset)) == NULL) { 20906f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("failed to read header\n"); 20916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher continue; 20926f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 20936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 20946f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 20956f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 20966f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 2097eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!lsonly) { 20986f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 2099eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher update_progress_bar(); 2100eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 21016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 2102a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 2103a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 2104443c15812032991c98b33b5424b17bcd55fe3575plougher } 2105443c15812032991c98b33b5424b17bcd55fe3575plougher 2106074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 2107074d3f1129eae914655f6637773488052bf22327rlougher set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); 2108443c15812032991c98b33b5424b17bcd55fe3575plougher 2109443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 2110443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 2111443c15812032991c98b33b5424b17bcd55fe3575plougher 2112443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 2113443c15812032991c98b33b5424b17bcd55fe3575plougher} 2114443c15812032991c98b33b5424b17bcd55fe3575plougher 2115443c15812032991c98b33b5424b17bcd55fe3575plougher 2116b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 2117b624936abba03d38b7e9245c647339d8f6f34274plougher{ 2118b624936abba03d38b7e9245c647339d8f6f34274plougher time_t mkfs_time = (time_t) sBlk.mkfs_time; 2119b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 2120b624936abba03d38b7e9245c647339d8f6f34274plougher 2121b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 2122b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); 2123b624936abba03d38b7e9245c647339d8f6f34274plougher#else 2124b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); 2125b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 2126b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); 2127b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); 2128b624936abba03d38b7e9245c647339d8f6f34274plougher 2129b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); 2130b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); 2131b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) 2132b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); 2133b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); 2134b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) { 2135b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); 2136b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); 2137b624936abba03d38b7e9245c647339d8f6f34274plougher } else 2138b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Fragments are not supported by the filesystem\n"); 2139b624936abba03d38b7e9245c647339d8f6f34274plougher 21400337de3977eec74e6a3d28e0d0863299246de8b7plougher if(sBlk.s_major > 1) 21410337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); 21420337de3977eec74e6a3d28e0d0863299246de8b7plougher else 21430337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 2144b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); 2145b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Block size %d\n", sBlk.block_size); 2146b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) 2147b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of fragments %d\n", sBlk.fragments); 2148b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of inodes %d\n", sBlk.inodes); 2149b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of uids %d\n", sBlk.no_uids); 2150b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of gids %d\n", sBlk.no_guids); 2151b624936abba03d38b7e9245c647339d8f6f34274plougher 2152b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); 2153b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); 2154b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 2155b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) 2156b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); 2157b624936abba03d38b7e9245c647339d8f6f34274plougher} 2158b624936abba03d38b7e9245c647339d8f6f34274plougher 2159b624936abba03d38b7e9245c647339d8f6f34274plougher 216002bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 2161443c15812032991c98b33b5424b17bcd55fe3575plougher{ 216202bc3bcabf2b219f63961f07293b83629948f026plougher read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); 2163443c15812032991c98b33b5424b17bcd55fe3575plougher 2164443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check it is a SQUASHFS superblock */ 2165443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 216602bc3bcabf2b219f63961f07293b83629948f026plougher if(sBlk.s_magic != SQUASHFS_MAGIC) { 216702bc3bcabf2b219f63961f07293b83629948f026plougher if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { 2168443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_super_block sblk; 2169443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); 217002bc3bcabf2b219f63961f07293b83629948f026plougher SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); 217102bc3bcabf2b219f63961f07293b83629948f026plougher memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); 2172443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 2173443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 2174443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Can't find a SQUASHFS superblock on %s\n", source); 2175443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 2176443c15812032991c98b33b5424b17bcd55fe3575plougher } 2177443c15812032991c98b33b5424b17bcd55fe3575plougher } 2178443c15812032991c98b33b5424b17bcd55fe3575plougher 2179443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 2180ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(sBlk.s_major == 1 || sBlk.s_major == 2) { 218102bc3bcabf2b219f63961f07293b83629948f026plougher sBlk.bytes_used = sBlk.bytes_used_2; 218202bc3bcabf2b219f63961f07293b83629948f026plougher sBlk.uid_start = sBlk.uid_start_2; 218302bc3bcabf2b219f63961f07293b83629948f026plougher sBlk.guid_start = sBlk.guid_start_2; 218402bc3bcabf2b219f63961f07293b83629948f026plougher sBlk.inode_table_start = sBlk.inode_table_start_2; 218502bc3bcabf2b219f63961f07293b83629948f026plougher sBlk.directory_table_start = sBlk.directory_table_start_2; 218602bc3bcabf2b219f63961f07293b83629948f026plougher 2187ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(sBlk.s_major == 1) { 2188ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher sBlk.block_size = sBlk.block_size_1; 2189ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher sBlk.fragment_table_start = sBlk.uid_start; 21906f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.squashfs_opendir = squashfs_opendir_2; 2191ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 2192ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 21936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 2194ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 2195ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher sBlk.fragment_table_start = sBlk.fragment_table_start_2; 2196ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.squashfs_opendir = squashfs_opendir_2; 2197ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 2198ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 2199ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list; 22006f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 2201ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 22024c99cb7f458d8e1c598f1c80793daf3696c9b528plougher } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { 220302bc3bcabf2b219f63961f07293b83629948f026plougher s_ops.squashfs_opendir = squashfs_opendir; 220402bc3bcabf2b219f63961f07293b83629948f026plougher s_ops.read_fragment = read_fragment; 220502bc3bcabf2b219f63961f07293b83629948f026plougher s_ops.read_fragment_table = read_fragment_table; 2206ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list; 22076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode; 220802bc3bcabf2b219f63961f07293b83629948f026plougher } else { 22094c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); 22104c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 2211443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 2212443c15812032991c98b33b5424b17bcd55fe3575plougher } 2213443c15812032991c98b33b5424b17bcd55fe3575plougher 2214443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 2215443c15812032991c98b33b5424b17bcd55fe3575plougher 2216443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 2217443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 2218443c15812032991c98b33b5424b17bcd55fe3575plougher} 2219443c15812032991c98b33b5424b17bcd55fe3575plougher 2220443c15812032991c98b33b5424b17bcd55fe3575plougher 2221a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 222271add234b27054974d5e29f95b3fab3072792a62plougher{ 222371add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 222471add234b27054974d5e29f95b3fab3072792a62plougher char name[16384]; 222571add234b27054974d5e29f95b3fab3072792a62plougher 22264dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if((fd = fopen(filename, "r")) == NULL) 22274dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); 222871add234b27054974d5e29f95b3fab3072792a62plougher 222971add234b27054974d5e29f95b3fab3072792a62plougher while(fscanf(fd, "%16384[^\n]\n", name) != EOF) 2230a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 223171add234b27054974d5e29f95b3fab3072792a62plougher 223271add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 2233a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 223471add234b27054974d5e29f95b3fab3072792a62plougher} 223571add234b27054974d5e29f95b3fab3072792a62plougher 223671add234b27054974d5e29f95b3fab3072792a62plougher 22378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* reader thread. This thread processes read requests queued by the 22388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * cache_get() routine. */ 22398888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 22408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 22418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 22428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 22438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int res = read_bytes(entry->block, 22448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 22458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 22468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 22488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* queue successfully read block to the deflate thread(s) 22498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * for further processing */ 22508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_deflate, entry); 22518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 22528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* block has either been successfully read and is uncompressed, 22538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * or an error has occurred, clear pending flag, set 22548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * error appropriately, and wake up any threads waiting on 22558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * this buffer */ 22568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 22578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 22598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* writer thread. This processes file write requests queued by the 22628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * write_file() routine. */ 22638888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 22648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 22658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 22668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 22688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 22698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 22708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hole = 0; 227127636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 22728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 22748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 22758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 22768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 22798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 22818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2282eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 22838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 22848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 22868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 22878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 22888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 22898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 229227636cb2cec37a68313f9eb825c0548245eecad0plougher 229327636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 229427636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 229527636cb2cec37a68313f9eb825c0548245eecad0plougher 229627636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE && write_block(file_fd, block->buffer->data + block->offset, block->size, hole) == FALSE) { 22978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("writer: failed to write data block %d\n", i); 229827636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 22998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 23018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 23028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 23038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 230527636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 23068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* corner case for hole extending to end of file */ 23078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(lseek(file_fd, hole, SEEK_CUR) == -1) { 23088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* for broken lseeks which cannot seek beyond end of 23098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * file, write_block will do the right thing */ 23108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 23118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(write_block(file_fd, "\0", 1, hole) == FALSE) { 23128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("writer: failed to write sparse data block\n"); 231327636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 23148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 23168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("writer: failed to write sparse data block\n"); 231727636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 23188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher close(file_fd); 232227636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 232327636cb2cec37a68313f9eb825c0548245eecad0plougher set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, force); 232427636cb2cec37a68313f9eb825c0548245eecad0plougher else { 232527636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 232627636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 232727636cb2cec37a68313f9eb825c0548245eecad0plougher } 232879df93becb68081effabebba3006c794be308598plougher free(file->pathname); 23298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 233027636cb2cec37a68313f9eb825c0548245eecad0plougher 23318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 23338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* decompress thread. This decompresses buffers queued by the read thread */ 23368888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *deflator(void *arg) 23378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 23388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 23398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 23418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_deflate); 23428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int res; 23438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned long bytes = block_size; 23448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher res = uncompress((unsigned char *) tmp, &bytes, (const unsigned char *) entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); 23468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res != Z_OK) { 23488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res == Z_MEM_ERROR) 23498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("zlib::uncompress failed, not enough memory\n"); 23508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else if(res == Z_BUF_ERROR) 23518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("zlib::uncompress failed, not enough room in output buffer\n"); 23528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 23538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("zlib::uncompress failed, unknown error %d\n", res); 23548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else 23558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memcpy(entry->data, tmp, bytes); 23568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* block has been either successfully decompressed, or an error 23588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 23598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * wake up any threads waiting on this block */ 23608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, res != Z_OK); 23618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 23638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2365eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 2366eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2367eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timeval timeval; 2368eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timespec timespec; 23691b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 23701b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 23711b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 23721b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 23731b42101056befe25b5f19d5b099e806a2ecee9cdplougher ERROR("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); 23741b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 23751b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 23761b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 23771b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 23781b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 23791b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 23801b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 23811b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 23821b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 23831b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 23841b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 2385eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2386eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_init(&progress_wait, NULL); 2387eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 23881b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2389eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 2390eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher gettimeofday(&timeval, NULL); 2391eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec = timeval.tv_sec; 2392eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(timeval.tv_usec + 250000 > 999999) 2393eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec++; 2394eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; 23951b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); 23961b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress_enabled) 23971b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 23981b42101056befe25b5f19d5b099e806a2ecee9cdplougher fifo_count + cur_blocks, total_inodes - total_files + 23991b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_blocks, columns); 2400eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2401eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2402eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2403eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 24048888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 24058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 24068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 24078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 24088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int all_buffers_size = fragment_buffer_size + data_buffer_size; 24098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 24118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGINT); 24128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 24138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 24148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); 24158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 24178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 24188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 24198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 24208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 24228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 24238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 24248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 24258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 24268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 24278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 24298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher ERROR("Failed to get number of available processors. Defaulting to 1\n"); 24308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 24318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 24328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 24338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = get_nprocs(); 24348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 24358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 24368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2437eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) 24388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 2439eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher deflator_thread = &thread[3]; 24408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_reader = queue_init(all_buffers_size); 24428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_deflate = queue_init(all_buffers_size); 2443eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher to_writer = queue_init(1000); 24448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 24458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 24468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 24478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 24488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 2449eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 24508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 24518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 24538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) 24548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 24558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 24568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 24588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 24598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) 24618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); 24628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 24638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 24651b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 24661b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 24671b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 24681b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = TRUE; 24691b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 24701b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 24711b42101056befe25b5f19d5b099e806a2ecee9cdplougher 24721b42101056befe25b5f19d5b099e806a2ecee9cdplougher 24731b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 24741b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 24751b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 24761b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 24771b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 24781b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 24791b42101056befe25b5f19d5b099e806a2ecee9cdplougher 24801b42101056befe25b5f19d5b099e806a2ecee9cdplougher 2481eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar() 2482eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 24831b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2484eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_signal(&progress_wait); 24851b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 2486eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2487eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2488eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2489eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 2490eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2491eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 2492eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int max_digits = ceil(log10(max)); 2493eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int used = max_digits * 2 + 11; 2494eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int hashes = (current * (columns - used)) / max; 2495eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int spaces = columns - used - hashes; 2496eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2497eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(current > max) { 2498eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("%lld %lld\n", current, max); 2499eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 2500eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2501eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2502eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!progress || columns - used < 0) 2503eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 2504eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2505eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 2506eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2507eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 2508eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 2509eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2510eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 2511eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2512eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 2513eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 2514eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2515eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 2516eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 2517eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 2518eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2519eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2520eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2521443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 25221b42101056befe25b5f19d5b099e806a2ecee9cdplougher printf("unsquashfs version 1.6-CVS (2008/05/01)\n");\ 252379df93becb68081effabebba3006c794be308598plougher printf("copyright (C) 2008 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ 2524443c15812032991c98b33b5424b17bcd55fe3575plougher printf("This program is free software; you can redistribute it and/or\n");\ 2525443c15812032991c98b33b5424b17bcd55fe3575plougher printf("modify it under the terms of the GNU General Public License\n");\ 2526443c15812032991c98b33b5424b17bcd55fe3575plougher printf("as published by the Free Software Foundation; either version 2,\n");\ 2527443c15812032991c98b33b5424b17bcd55fe3575plougher printf("or (at your option) any later version.\n\n");\ 2528443c15812032991c98b33b5424b17bcd55fe3575plougher printf("This program is distributed in the hope that it will be useful,\n");\ 2529443c15812032991c98b33b5424b17bcd55fe3575plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ 2530443c15812032991c98b33b5424b17bcd55fe3575plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ 2531443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 2532443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 2533443c15812032991c98b33b5424b17bcd55fe3575plougher{ 2534443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 2535b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 2536545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 2537a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 2538a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 2539ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 2540ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 25410cf5c297bec42c7c220d2825f12f9499f2293279plougher char *b; 2542eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 2543443c15812032991c98b33b5424b17bcd55fe3575plougher 25441b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 2545545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 2546545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 25479dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 25489dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 2549443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 2550443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 2551443c15812032991c98b33b5424b17bcd55fe3575plougher break; 2552a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { 2553443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 2554443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 2555a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) 2556443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 2557a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) 2558443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 2559a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { 256071add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 256171add234b27054974d5e29f95b3fab3072792a62plougher fprintf(stderr, "%s: -dest missing filename\n", argv[0]); 256271add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 256371add234b27054974d5e29f95b3fab3072792a62plougher } 2564443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 25650cf5c297bec42c7c220d2825f12f9499f2293279plougher } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { 25660cf5c297bec42c7c220d2825f12f9499f2293279plougher if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { 25670cf5c297bec42c7c220d2825f12f9499f2293279plougher ERROR("%s: -processors missing or invalid processor number\n", argv[0]); 25680cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 25690cf5c297bec42c7c220d2825f12f9499f2293279plougher } 25700cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 25710cf5c297bec42c7c220d2825f12f9499f2293279plougher ERROR("%s: -processors should be 1 or larger\n", argv[0]); 25720cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 25730cf5c297bec42c7c220d2825f12f9499f2293279plougher } 2574ae271cc93e3684d5314bcdc45b631e497ae43166plougher } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { 2575ae271cc93e3684d5314bcdc45b631e497ae43166plougher if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { 2576ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("%s: -data-queue missing or invalid queue size\n", argv[0]); 2577ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2578ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2579ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 2580ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("%s: -data-queue should be 1 Mbyte or larger\n", argv[0]); 2581ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2582ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2583ae271cc93e3684d5314bcdc45b631e497ae43166plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { 2584ae271cc93e3684d5314bcdc45b631e497ae43166plougher if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { 2585ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("%s: -frag-queue missing or invalid queue size\n", argv[0]); 2586ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2587ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2588ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 2589ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("%s: -frag-queue should be 1 Mbyte or larger\n", argv[0]); 2590ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2591ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2592a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) 2593a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 2594b624936abba03d38b7e9245c647339d8f6f34274plougher else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) 2595b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 25969baf35a00f38816d2054deb70184943d0686d03eplougher else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { 25979baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 25989baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 25993edfa57b6a463f7d441d995559143f4861d62e98plougher } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { 26009baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 26019baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 260271add234b27054974d5e29f95b3fab3072792a62plougher } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { 260371add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 260471add234b27054974d5e29f95b3fab3072792a62plougher fprintf(stderr, "%s: -ef missing filename\n", argv[0]); 260571add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 260671add234b27054974d5e29f95b3fab3072792a62plougher } 2607a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 26084dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) 26094dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 26104dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2611b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2612443c15812032991c98b33b5424b17bcd55fe3575plougher } 2613443c15812032991c98b33b5424b17bcd55fe3575plougher 2614443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2615443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2616443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 261771add234b27054974d5e29f95b3fab3072792a62plougher ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); 2618a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); 26190cf5c297bec42c7c220d2825f12f9499f2293279plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); 26200cf5c297bec42c7c220d2825f12f9499f2293279plougher ERROR("\t-p[rocessors] <number>\tuse <number> processors. By default will use\n\t\t\t\tnumber of processors available\n"); 2621a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); 26229baf35a00f38816d2054deb70184943d0686d03eplougher ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); 26239baf35a00f38816d2054deb70184943d0686d03eplougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); 26249baf35a00f38816d2054deb70184943d0686d03eplougher ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); 2625a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); 26260337de3977eec74e6a3d28e0d0863299246de8b7plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); 262771add234b27054974d5e29f95b3fab3072792a62plougher ERROR("\t-e[f] <extract file>\tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); 2628ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("\t-da[ta-queue] <size>\tSet data queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); 2629ae271cc93e3684d5314bcdc45b631e497ae43166plougher ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", FRAGMENT_BUFFER_DEFAULT); 26304dba330d7b952f2f044d38e342e2ae3ea78910d6plougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); 2631443c15812032991c98b33b5424b17bcd55fe3575plougher } 2632443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2633443c15812032991c98b33b5424b17bcd55fe3575plougher } 2634443c15812032991c98b33b5424b17bcd55fe3575plougher 263571add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2636a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2637b54566f5c433764830c29c83151691d0034de094plougher 2638443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2639443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); 2640443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2641443c15812032991c98b33b5424b17bcd55fe3575plougher } 2642443c15812032991c98b33b5424b17bcd55fe3575plougher 264302bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2644443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2645443c15812032991c98b33b5424b17bcd55fe3575plougher 2646b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2647b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2648b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2649b624936abba03d38b7e9245c647339d8f6f34274plougher } 2650b624936abba03d38b7e9245c647339d8f6f34274plougher 2651443c15812032991c98b33b5424b17bcd55fe3575plougher block_size = sBlk.block_size; 2652ae271cc93e3684d5314bcdc45b631e497ae43166plougher block_log = sBlk.block_log; 2653ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2654ae271cc93e3684d5314bcdc45b631e497ae43166plougher fragment_buffer_size <<= 20 - block_log; 2655ae271cc93e3684d5314bcdc45b631e497ae43166plougher data_buffer_size <<= 20 - block_log; 26568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 26578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2658443c15812032991c98b33b5424b17bcd55fe3575plougher if((fragment_data = malloc(block_size)) == NULL) 2659443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2660443c15812032991c98b33b5424b17bcd55fe3575plougher 2661443c15812032991c98b33b5424b17bcd55fe3575plougher if((file_data = malloc(block_size)) == NULL) 2662443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2663443c15812032991c98b33b5424b17bcd55fe3575plougher 2664443c15812032991c98b33b5424b17bcd55fe3575plougher if((data = malloc(block_size)) == NULL) 2665eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2666443c15812032991c98b33b5424b17bcd55fe3575plougher 2667443c15812032991c98b33b5424b17bcd55fe3575plougher if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) 2668443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2669443c15812032991c98b33b5424b17bcd55fe3575plougher 2670443c15812032991c98b33b5424b17bcd55fe3575plougher memset(created_inode, 0, sBlk.inodes * sizeof(char *)); 2671443c15812032991c98b33b5424b17bcd55fe3575plougher 267202bc3bcabf2b219f63961f07293b83629948f026plougher read_uids_guids(); 2673ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 267402bc3bcabf2b219f63961f07293b83629948f026plougher s_ops.read_fragment_table(); 2675ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 267602bc3bcabf2b219f63961f07293b83629948f026plougher uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); 2677ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 267802bc3bcabf2b219f63961f07293b83629948f026plougher uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); 2679443c15812032991c98b33b5424b17bcd55fe3575plougher 2680a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2681a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2682a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2683a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2684a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 2685eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); 2686eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2687eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher memset(created_inode, 0, sBlk.inodes * sizeof(char *)); 2688eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2689eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("%d files (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); 2690eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 26911b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 26921b42101056befe25b5f19d5b099e806a2ecee9cdplougher enable_progress_bar(); 26931b42101056befe25b5f19d5b099e806a2ecee9cdplougher 269471add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); 2695443c15812032991c98b33b5424b17bcd55fe3575plougher 26968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 26978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 26988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 26991b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 27001b42101056befe25b5f19d5b099e806a2ecee9cdplougher disable_progress_bar(); 27011b42101056befe25b5f19d5b099e806a2ecee9cdplougher 27021b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 27031b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_inodes - total_files + total_blocks, columns); 2704eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2705443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2706443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2707443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2708443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2709443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2710443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2711443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2712443c15812032991c98b33b5424b17bcd55fe3575plougher } 2713eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 27149dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2715443c15812032991c98b33b5424b17bcd55fe3575plougher} 2716