unsquashfs.c revision 0ca44ca7b28597911258e0c27bd82feef73f2256
12f60990fb0352f7a30e0281a066458dbf033618bplougher/* 2e3206fad5b70e7e0527db2a627ad26616a8a2429plougher * Unsquash a squashfs filesystem. This is a highly compressed read only 3e3206fad5b70e7e0527db2a627ad26616a8a2429plougher * filesystem. 4443c15812032991c98b33b5424b17bcd55fe3575plougher * 50ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 60ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher * 2012 779df93becb68081effabebba3006c794be308598plougher * Phillip Lougher <phillip@lougher.demon.co.uk> 8443c15812032991c98b33b5424b17bcd55fe3575plougher * 9443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is free software; you can redistribute it and/or 10443c15812032991c98b33b5424b17bcd55fe3575plougher * modify it under the terms of the GNU General Public License 11443c15812032991c98b33b5424b17bcd55fe3575plougher * as published by the Free Software Foundation; either version 2, 12443c15812032991c98b33b5424b17bcd55fe3575plougher * or (at your option) any later version. 13443c15812032991c98b33b5424b17bcd55fe3575plougher * 14443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is distributed in the hope that it will be useful, 15443c15812032991c98b33b5424b17bcd55fe3575plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 16443c15812032991c98b33b5424b17bcd55fe3575plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17443c15812032991c98b33b5424b17bcd55fe3575plougher * GNU General Public License for more details. 18443c15812032991c98b33b5424b17bcd55fe3575plougher * 19443c15812032991c98b33b5424b17bcd55fe3575plougher * You should have received a copy of the GNU General Public License 20443c15812032991c98b33b5424b17bcd55fe3575plougher * along with this program; if not, write to the Free Software 21443c15812032991c98b33b5424b17bcd55fe3575plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22443c15812032991c98b33b5424b17bcd55fe3575plougher * 23ed5124f016834932db2c63d60d259d846171c216plougher * unsquashfs.c 24443c15812032991c98b33b5424b17bcd55fe3575plougher */ 25443c15812032991c98b33b5424b17bcd55fe3575plougher 26ed5124f016834932db2c63d60d259d846171c216plougher#include "unsquashfs.h" 276490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "squashfs_swap.h" 286490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "squashfs_compat.h" 296490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "read_fs.h" 30efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher#include "compressor.h" 312ef25cb004cc6995bd36f781863aa844fe8c358dplougher#include "xattr.h" 328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 33cdebd2b8ae4b1ac39eefb5f0c556f0d2e3dc3d24plougher#include <sys/sysinfo.h> 342ef25cb004cc6995bd36f781863aa844fe8c358dplougher#include <sys/types.h> 35cdebd2b8ae4b1ac39eefb5f0c556f0d2e3dc3d24plougher 368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *fragment_cache, *data_cache; 378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *to_reader, *to_deflate, *to_writer, *from_writer; 388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_t *thread, *deflator_thread; 398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_mutex_t fragment_mutex; 408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* user options that control parallelisation */ 428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint processors = -1; 438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 446490378e5b5e8dc058daf28423a7465699a6ba7bplougherstruct super_block sBlk; 4502bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_operations s_ops; 46efda88fd6fbb19543a86b5f8d15b437bba8c4674plougherstruct compressor *comp; 4702bc3bcabf2b219f63961f07293b83629948f026plougher 489dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, 499dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher dev_count = 0, fifo_count = 0; 50443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 51443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 52443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 53443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 54443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 55443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 56443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 57443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 58443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 59ae271cc93e3684d5314bcdc45b631e497ae43166plougherunsigned int block_log; 60d4204758f77acb5a371fa1487a755b76a05d5476plougherint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; 61d4204758f77acb5a371fa1487a755b76a05d5476plougherint use_regex = FALSE; 62443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 639dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint root_process; 64eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint columns; 65eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint rotate = 0; 661b42101056befe25b5f19d5b099e806a2ecee9cdplougherpthread_mutex_t screen_mutex; 67eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherpthread_cond_t progress_wait; 681b42101056befe25b5f19d5b099e806a2ecee9cdplougherint progress = TRUE, progress_enabled = FALSE; 69eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int total_blocks = 0, total_files = 0, total_inodes = 0; 70eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int cur_blocks = 0; 71ed5124f016834932db2c63d60d259d846171c216plougherint inode_number = 1; 72df9d38a515489c2c573754ad81abd230dfd8b1f0plougherint no_xattrs = XATTR_DEF; 73443c15812032991c98b33b5424b17bcd55fe3575plougher 74476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 75476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 76476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 77476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 78476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 79476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 80476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 81476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 82476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 83476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 84eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFREG, 85eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFLNK, 86eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFBLK, 87eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFCHR, 88eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFIFO, 89eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFSOCK 90476dcb48b24efff22caa970f000e151f1b28918dplougher}; 91476dcb48b24efff22caa970f000e151f1b28918dplougher 92476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 93476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 94476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 95476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 96476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 97476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 98476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 99476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 100476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 101476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 102476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 103476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 104476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 105476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 106476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 107476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 108476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 109476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 110476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 111476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 112476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 113476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 1148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 1158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 117eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 118eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar(); 119eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 120eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 121eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 124eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 125c27a3d72b339d80d38623a4ee5a42601338fb4c9plougher if(isatty(STDOUT_FILENO)) 126d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 127d4204758f77acb5a371fa1487a755b76a05d5476plougher "columns\n"); 128eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 129eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 130eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 131eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 132eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1341b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 1351b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 1361b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 1371b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 1381b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1391b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 1418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 1438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 14562b2d7649ad84234afd928a43f9a2c1612eef361plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1477b53be8c83b949517c343d9c6d88243578753c3aplougher queue->data = malloc(sizeof(void *) * (size + 1)); 1487b53be8c83b949517c343d9c6d88243578753c3aplougher if(queue->data == NULL) 1490e0cc6f6dccdc5460c292b0a5accc1184a07f3f5plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 1528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 1538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 1548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 1558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 1568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 1588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1618888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 1628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 1648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 1688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 1698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 1718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 1728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 1738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 1748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1778888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 1788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 1808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 1868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 1878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 1888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 1898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 1918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 1958888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 1968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 1988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 2008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 2018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 2028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 2048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2088888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 2098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 2118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 2128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 213c435240f52b78b0ef498118727ba8dad186db26bplougher cache->hash_table[CALCULATE_HASH(entry->block)] = 214c435240f52b78b0ef498118727ba8dad186db26bplougher entry->hash_next; 2158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 2178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 2198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2238888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 2248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 2268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 2278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 2288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 2298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 2308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 2328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 2338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2388888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 2398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->free_prev == NULL && entry->free_next == NULL) 2418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 2428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 243222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 2448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 2458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 2488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 2528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 2558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 2598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 2618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 263360570574b8f7786728d91d5fe4a0a4aa291fa03plougher EXIT_UNSQUASH("Out of memory in cache_init\n"); 2648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 2678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 2688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 2708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 2718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 2728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 2738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 2748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 2758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 2778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 282d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 283d4204758f77acb5a371fa1487a755b76a05d5476plougher * Get a block out of the cache. If the block isn't in the cache 284d4204758f77acb5a371fa1487a755b76a05d5476plougher * it is added and queued to the reader() and deflate() threads for 285c435240f52b78b0ef498118727ba8dad186db26bplougher * reading off disk and decompression. The cache grows until max_blocks 286c435240f52b78b0ef498118727ba8dad186db26bplougher * is reached, once this occurs existing discarded blocks on the free 287c435240f52b78b0ef498118727ba8dad186db26bplougher * list are reused 288d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 2908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 2918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 299d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 3000a0d045642e8e413f90b770539193d3fd1522786plougher * found the block in the cache, increment used count and 3018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * if necessary remove from free list so it won't disappear 3028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 307d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 308d4204758f77acb5a371fa1487a755b76a05d5476plougher * not in the cache 309d4204758f77acb5a371fa1487a755b76a05d5476plougher * 310d4204758f77acb5a371fa1487a755b76a05d5476plougher * first try to allocate new block 311d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 3138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 3148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 3157227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 3177227416360c2f249a0783dffef6725ad03b61c99plougher if(entry->data == NULL) 3187227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 3228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 323d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 324d4204758f77acb5a371fa1487a755b76a05d5476plougher * try to get from free list 325d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 3278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 328d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&cache->wait_for_free, 329d4204758f77acb5a371fa1487a755b76a05d5476plougher &cache->mutex); 3308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 3328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 3348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 336d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 337d4204758f77acb5a371fa1487a755b76a05d5476plougher * initialise block and insert into the hash table 338d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 3408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 3438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 3448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 3458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 346d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 347c435240f52b78b0ef498118727ba8dad186db26bplougher * queue to read thread to read and ultimately (via the 348c435240f52b78b0ef498118727ba8dad186db26bplougher * decompress threads) decompress the buffer 3498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 3528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 3558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3588888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 3598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 360d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 361d4204758f77acb5a371fa1487a755b76a05d5476plougher * mark cache entry as being complete, reading and (if necessary) 3628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 3638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 364d4204758f77acb5a371fa1487a755b76a05d5476plougher * becomes ready but with an error... 365d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 3688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 3698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 370d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 371c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_pending flag is set, one or more threads may be waiting 372c435240f52b78b0ef498118727ba8dad186db26bplougher * on this buffer 373d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 3758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 3768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 3778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 3808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3838888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 3848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 385d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 386d4204758f77acb5a371fa1487a755b76a05d5476plougher * wait for this cache entry to become ready, when reading and (if 387d4204758f77acb5a371fa1487a755b76a05d5476plougher * necessary) decompression has taken place 388d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 3928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 393d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&entry->cache->wait_for_pending, 394d4204758f77acb5a371fa1487a755b76a05d5476plougher &entry->cache->mutex); 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 3988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4018888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 4028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 403d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 404d4204758f77acb5a371fa1487a755b76a05d5476plougher * finished with this cache entry, once the usage count reaches zero it 405c435240f52b78b0ef498118727ba8dad186db26bplougher * can be reused and is put onto the free list. As it remains 406c435240f52b78b0ef498118727ba8dad186db26bplougher * accessible via the hash table it can be found getting a new lease of 407c435240f52b78b0ef498118727ba8dad186db26bplougher * life before it is reused. 408d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 4128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 4138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 4148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 415d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 416c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_free flag is set, one or more threads may be 417c435240f52b78b0ef498118727ba8dad186db26bplougher * waiting on this buffer 418d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 4218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 4228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 427476dcb48b24efff22caa970f000e151f1b28918dplougher 428476dcb48b24efff22caa970f000e151f1b28918dplougher 429476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 430476dcb48b24efff22caa970f000e151f1b28918dplougher{ 431476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 432476dcb48b24efff22caa970f000e151f1b28918dplougher 433476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 434476dcb48b24efff22caa970f000e151f1b28918dplougher 435476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 436476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 437476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 438476dcb48b24efff22caa970f000e151f1b28918dplougher } 439476dcb48b24efff22caa970f000e151f1b28918dplougher 440476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 441476dcb48b24efff22caa970f000e151f1b28918dplougher} 442476dcb48b24efff22caa970f000e151f1b28918dplougher 443476dcb48b24efff22caa970f000e151f1b28918dplougher 4443edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 4456f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 446476dcb48b24efff22caa970f000e151f1b28918dplougher{ 4476f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher char str[11], dummy[100], dummy2[100], *userstr, *groupstr; 4486f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 449476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 450476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 45188facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 452476dcb48b24efff22caa970f000e151f1b28918dplougher 453476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 454476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 455476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 456476dcb48b24efff22caa970f000e151f1b28918dplougher } 457476dcb48b24efff22caa970f000e151f1b28918dplougher 458266b83c3b162a6764407753909712fcaade951f2plougher user = getpwuid(inode->uid); 459266b83c3b162a6764407753909712fcaade951f2plougher if(user == NULL) { 4606f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy, "%d", inode->uid); 4613edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = dummy; 4623edfa57b6a463f7d441d995559143f4861d62e98plougher } else 4633edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 4643edfa57b6a463f7d441d995559143f4861d62e98plougher 465266b83c3b162a6764407753909712fcaade951f2plougher group = getgrgid(inode->gid); 466266b83c3b162a6764407753909712fcaade951f2plougher if(group == NULL) { 4676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy2, "%d", inode->gid); 4683edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = dummy2; 4693edfa57b6a463f7d441d995559143f4861d62e98plougher } else 4703edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 4713edfa57b6a463f7d441d995559143f4861d62e98plougher 4726f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 4733edfa57b6a463f7d441d995559143f4861d62e98plougher 4746f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 4753edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 4763edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 4773edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 4783edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 4793edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 480c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 481c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr); 4823edfa57b6a463f7d441d995559143f4861d62e98plougher 483c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%*lld ", padchars > 0 ? padchars : 0, 484c435240f52b78b0ef498118727ba8dad186db26bplougher inode->data); 4853edfa57b6a463f7d441d995559143f4861d62e98plougher break; 4863edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 4873edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 488c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 489c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr) - 7; 4903edfa57b6a463f7d441d995559143f4861d62e98plougher 491d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", 492c435240f52b78b0ef498118727ba8dad186db26bplougher (int) inode->data >> 8, (int) inode->data & 493c435240f52b78b0ef498118727ba8dad186db26bplougher 0xff); 4943edfa57b6a463f7d441d995559143f4861d62e98plougher break; 4953edfa57b6a463f7d441d995559143f4861d62e98plougher } 496476dcb48b24efff22caa970f000e151f1b28918dplougher 4976f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 49888facddfd83e48a907b82210ddccbb4f84d80aecplougher 499d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, 500d4204758f77acb5a371fa1487a755b76a05d5476plougher t->tm_mday, t->tm_hour, t->tm_min, pathname); 5016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 5026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 5033edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 5043edfa57b6a463f7d441d995559143f4861d62e98plougher 505476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 506476dcb48b24efff22caa970f000e151f1b28918dplougher} 507476dcb48b24efff22caa970f000e151f1b28918dplougher 508443c15812032991c98b33b5424b17bcd55fe3575plougher 509e3206fad5b70e7e0527db2a627ad26616a8a2429ploughervoid add_entry(struct hash_table_entry *hash_table[], long long start, 510e3206fad5b70e7e0527db2a627ad26616a8a2429plougher int bytes) 511443c15812032991c98b33b5424b17bcd55fe3575plougher{ 512443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 513443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 514443c15812032991c98b33b5424b17bcd55fe3575plougher 515cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher hash_table_entry = malloc(sizeof(struct hash_table_entry)); 516cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher if(hash_table_entry == NULL) 5174a39fa82d4614c18d2977be7898d78d20ba01a49plougher EXIT_UNSQUASH("Out of memory in add_entry\n"); 518443c15812032991c98b33b5424b17bcd55fe3575plougher 519443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 520443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 521443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 522443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 523443c15812032991c98b33b5424b17bcd55fe3575plougher} 524443c15812032991c98b33b5424b17bcd55fe3575plougher 525443c15812032991c98b33b5424b17bcd55fe3575plougher 526f404f4914fdb272a70e18664e8963d793cc90f44plougherint lookup_entry(struct hash_table_entry *hash_table[], long long start) 527443c15812032991c98b33b5424b17bcd55fe3575plougher{ 528443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 529443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 530443c15812032991c98b33b5424b17bcd55fe3575plougher 5319dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 5329dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 5337a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher 534443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 535443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 536443c15812032991c98b33b5424b17bcd55fe3575plougher 537443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 538443c15812032991c98b33b5424b17bcd55fe3575plougher} 539443c15812032991c98b33b5424b17bcd55fe3575plougher 540443c15812032991c98b33b5424b17bcd55fe3575plougher 5413306cb2b54a60a32664617118336ac141e1471b6plougherint read_fs_bytes(int fd, long long byte, int bytes, void *buff) 542443c15812032991c98b33b5424b17bcd55fe3575plougher{ 543443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 544d7f3de3408089ce187d8bc26f6072730c77628daplougher int res, count; 545443c15812032991c98b33b5424b17bcd55fe3575plougher 546c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, 547c435240f52b78b0ef498118727ba8dad186db26bplougher bytes); 548fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 549443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 5505d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 551443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 552443c15812032991c98b33b5424b17bcd55fe3575plougher } 553443c15812032991c98b33b5424b17bcd55fe3575plougher 554d7f3de3408089ce187d8bc26f6072730c77628daplougher for(count = 0; count < bytes; count += res) { 555d7f3de3408089ce187d8bc26f6072730c77628daplougher res = read(fd, buff + count, bytes - count); 556d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res < 1) { 557d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res == 0) { 558e3206fad5b70e7e0527db2a627ad26616a8a2429plougher ERROR("Read on filesystem failed because " 559e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "EOF\n"); 560d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 561d7f3de3408089ce187d8bc26f6072730c77628daplougher } else if(errno != EINTR) { 562d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because %s\n", 563d7f3de3408089ce187d8bc26f6072730c77628daplougher strerror(errno)); 564d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 565d7f3de3408089ce187d8bc26f6072730c77628daplougher } else 566d7f3de3408089ce187d8bc26f6072730c77628daplougher res = 0; 567d7f3de3408089ce187d8bc26f6072730c77628daplougher } 568443c15812032991c98b33b5424b17bcd55fe3575plougher } 569443c15812032991c98b33b5424b17bcd55fe3575plougher 570443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 571443c15812032991c98b33b5424b17bcd55fe3575plougher} 572443c15812032991c98b33b5424b17bcd55fe3575plougher 573443c15812032991c98b33b5424b17bcd55fe3575plougher 574923b301e304637fd5e587eb05a6f44558abae2bdplougherint read_block(int fd, long long start, long long *next, void *block) 575443c15812032991c98b33b5424b17bcd55fe3575plougher{ 576443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 577443c15812032991c98b33b5424b17bcd55fe3575plougher int offset = 2; 578443c15812032991c98b33b5424b17bcd55fe3575plougher 579443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 580923b301e304637fd5e587eb05a6f44558abae2bdplougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 581fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 582923b301e304637fd5e587eb05a6f44558abae2bdplougher c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); 583443c15812032991c98b33b5424b17bcd55fe3575plougher } else 5843306cb2b54a60a32664617118336ac141e1471b6plougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 585fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 586fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 587d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, 588d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? 589d4204758f77acb5a371fa1487a755b76a05d5476plougher "compressed" : "uncompressed"); 590443c15812032991c98b33b5424b17bcd55fe3575plougher 59127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) 592443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 593443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED(c_byte)) { 594443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[SQUASHFS_METADATA_SIZE]; 595efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 596443c15812032991c98b33b5424b17bcd55fe3575plougher 597443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 59886561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start + offset, c_byte, buffer) == FALSE) 599fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 600443c15812032991c98b33b5424b17bcd55fe3575plougher 601b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, buffer, c_byte, 602efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_METADATA_SIZE, &error); 603efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 604efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 605efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 606efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 607fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 608443c15812032991c98b33b5424b17bcd55fe3575plougher } 609443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 610443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 611efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 612443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 613443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 61486561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start + offset, c_byte, block) == FALSE) 615fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 616443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 617443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 618443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 619443c15812032991c98b33b5424b17bcd55fe3575plougher } 620fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 621fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 62268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher ERROR("read_block: failed to read block @0x%llx\n", start); 623fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 624443c15812032991c98b33b5424b17bcd55fe3575plougher} 625443c15812032991c98b33b5424b17bcd55fe3575plougher 626443c15812032991c98b33b5424b17bcd55fe3575plougher 627443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 628443c15812032991c98b33b5424b17bcd55fe3575plougher{ 629efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 630443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 631443c15812032991c98b33b5424b17bcd55fe3575plougher 632d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, 633c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : 634c435240f52b78b0ef498118727ba8dad186db26bplougher "uncompressed"); 635fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 636443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 63786561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, data) == FALSE) 63868ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 639443c15812032991c98b33b5424b17bcd55fe3575plougher 640b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, data, c_byte, 641b48442b2e37b3cb7efbffb032968f115eec7963cplougher block_size, &error); 642efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 643efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 644efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 645efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 64668ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 647443c15812032991c98b33b5424b17bcd55fe3575plougher } 648443c15812032991c98b33b5424b17bcd55fe3575plougher 649efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 650443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 65186561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, block) == FALSE) 65268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 653443c15812032991c98b33b5424b17bcd55fe3575plougher 654443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 655443c15812032991c98b33b5424b17bcd55fe3575plougher } 65668ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher 65768ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougherfailed: 658d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, 659c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte); 66068ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher return FALSE; 661443c15812032991c98b33b5424b17bcd55fe3575plougher} 662443c15812032991c98b33b5424b17bcd55fe3575plougher 663443c15812032991c98b33b5424b17bcd55fe3575plougher 66402bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_inode_table(long long start, long long end) 665443c15812032991c98b33b5424b17bcd55fe3575plougher{ 666443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 667443c15812032991c98b33b5424b17bcd55fe3575plougher 66841da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); 669443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 670c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 671c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher inode_table = realloc(inode_table, size += 672c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher SQUASHFS_METADATA_SIZE); 673c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(inode_table == NULL) 674c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher EXIT_UNSQUASH("Out of memory in " 675c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher "uncompress_inode_table"); 676c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher } 677443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_inode_table: reading block 0x%llx\n", start); 678443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 679176b325add10f6b9846f771f75d8543364d4c121plougher res = read_block(fd, start, &start, inode_table + bytes); 680c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) { 681443c15812032991c98b33b5424b17bcd55fe3575plougher free(inode_table); 682d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_inode_table: failed to read " 683d4204758f77acb5a371fa1487a755b76a05d5476plougher "block \n"); 684443c15812032991c98b33b5424b17bcd55fe3575plougher } 685443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 686443c15812032991c98b33b5424b17bcd55fe3575plougher } 687443c15812032991c98b33b5424b17bcd55fe3575plougher} 688443c15812032991c98b33b5424b17bcd55fe3575plougher 689443c15812032991c98b33b5424b17bcd55fe3575plougher 690d4204758f77acb5a371fa1487a755b76a05d5476plougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, 691fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher unsigned int xattr, unsigned int set_mode) 692443c15812032991c98b33b5424b17bcd55fe3575plougher{ 6936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 694443c15812032991c98b33b5424b17bcd55fe3575plougher 6952ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, xattr); 6962ef25cb004cc6995bd36f781863aa844fe8c358dplougher 697443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 698d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to set time on %s, because %s\n", 699d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 700443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 701443c15812032991c98b33b5424b17bcd55fe3575plougher } 702443c15812032991c98b33b5424b17bcd55fe3575plougher 7039dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 7046f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 705c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("set_attributes: failed to change uid and gids " 706c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s, because %s\n", pathname, 707c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 708443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 709443c15812032991c98b33b5424b17bcd55fe3575plougher } 7109dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 7119dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 7129dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 7139dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 714d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change mode %s, because %s\n", 715d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 7169dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 717443c15812032991c98b33b5424b17bcd55fe3575plougher } 718443c15812032991c98b33b5424b17bcd55fe3575plougher 719443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 720443c15812032991c98b33b5424b17bcd55fe3575plougher} 721443c15812032991c98b33b5424b17bcd55fe3575plougher 722443c15812032991c98b33b5424b17bcd55fe3575plougher 7231c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougherint write_bytes(int fd, char *buff, int bytes) 7241c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher{ 7251c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher int res, count; 7261c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7271c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher for(count = 0; count < bytes; count += res) { 7281c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = write(fd, buff + count, bytes - count); 7291c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(res == -1) { 7301c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(errno != EINTR) { 731c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Write on output file failed because " 732c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", strerror(errno)); 7331c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return -1; 7341c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7351c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = 0; 7361c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7371c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7381c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7391c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return 0; 7401c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher} 7411c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7421c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 743b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 744c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherchar *zero_data = NULL; 745b9cee889506e674726856035dba52d5e1cceeb99plougher 74687f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougherint write_block(int file_fd, char *buffer, int size, long long hole, int sparse) 747b9cee889506e674726856035dba52d5e1cceeb99plougher{ 748b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 749b9cee889506e674726856035dba52d5e1cceeb99plougher 750b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 751c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse && lseek_broken == FALSE) { 752c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error = lseek(file_fd, off, SEEK_CUR); 753c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == -1) 754c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher /* failed to seek beyond end of file */ 755c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher lseek_broken = TRUE; 756c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher } 757c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 758c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if((sparse == FALSE || lseek_broken) && zero_data == NULL) { 759b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 760c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("write_block: failed to alloc " 761c435240f52b78b0ef498118727ba8dad186db26bplougher "zero data block\n"); 762b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 763b9cee889506e674726856035dba52d5e1cceeb99plougher } 764c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 765c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse == FALSE || lseek_broken) { 766b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 767b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 768b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 769d4204758f77acb5a371fa1487a755b76a05d5476plougher avail_bytes = hole > block_size ? block_size : 770d4204758f77acb5a371fa1487a755b76a05d5476plougher hole; 771d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_bytes(file_fd, zero_data, avail_bytes) 772d4204758f77acb5a371fa1487a755b76a05d5476plougher == -1) 773b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 774b9cee889506e674726856035dba52d5e1cceeb99plougher } 775b9cee889506e674726856035dba52d5e1cceeb99plougher } 776b9cee889506e674726856035dba52d5e1cceeb99plougher } 777b9cee889506e674726856035dba52d5e1cceeb99plougher 7781c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(write_bytes(file_fd, buffer, size) == -1) 779b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 780b9cee889506e674726856035dba52d5e1cceeb99plougher 781b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 782b9cee889506e674726856035dba52d5e1cceeb99plougher 783b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 784b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 785b9cee889506e674726856035dba52d5e1cceeb99plougher} 786b9cee889506e674726856035dba52d5e1cceeb99plougher 7878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 78879df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 789443c15812032991c98b33b5424b17bcd55fe3575plougher{ 7908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 791f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 79279df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 79379df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 7948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file; 795443c15812032991c98b33b5424b17bcd55fe3575plougher 79679df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 797443c15812032991c98b33b5424b17bcd55fe3575plougher 798d4204758f77acb5a371fa1487a755b76a05d5476plougher file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), 799d4204758f77acb5a371fa1487a755b76a05d5476plougher (mode_t) inode->mode & 0777); 800d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file_fd == -1) { 801d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("write_file: failed to create file %s, because %s\n", 802d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 803443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 804443c15812032991c98b33b5424b17bcd55fe3575plougher } 805443c15812032991c98b33b5424b17bcd55fe3575plougher 8066037584bc3e861ff932f5244105959c56c8560e3plougher block_list = malloc(inode->blocks * sizeof(unsigned int)); 8076037584bc3e861ff932f5244105959c56c8560e3plougher if(block_list == NULL) 8088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 809443c15812032991c98b33b5424b17bcd55fe3575plougher 81079df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 811443c15812032991c98b33b5424b17bcd55fe3575plougher 8126037584bc3e861ff932f5244105959c56c8560e3plougher file = malloc(sizeof(struct squashfs_file)); 8136037584bc3e861ff932f5244105959c56c8560e3plougher if(file == NULL) 8148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 815443c15812032991c98b33b5424b17bcd55fe3575plougher 816d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 817d4204758f77acb5a371fa1487a755b76a05d5476plougher * the writer thread is queued a squashfs_file structure describing the 818c435240f52b78b0ef498118727ba8dad186db26bplougher * file. If the file has one or more blocks or a fragments they are 819c435240f52b78b0ef498118727ba8dad186db26bplougher * queued separately (references to blocks in the cache). 820d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 8218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file->fd = file_fd; 82279df93becb68081effabebba3006c794be308598plougher file->file_size = inode->data; 82379df93becb68081effabebba3006c794be308598plougher file->mode = inode->mode; 82479df93becb68081effabebba3006c794be308598plougher file->gid = inode->gid; 82579df93becb68081effabebba3006c794be308598plougher file->uid = inode->uid; 82679df93becb68081effabebba3006c794be308598plougher file->time = inode->time; 82779df93becb68081effabebba3006c794be308598plougher file->pathname = strdup(pathname); 82879df93becb68081effabebba3006c794be308598plougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 8297f6692575a1b1c8d7d55afac647b72b84b79e378plougher file->sparse = inode->sparse; 830fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher file->xattr = inode->xattr; 8318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, file); 832443c15812032991c98b33b5424b17bcd55fe3575plougher 83379df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 8348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 8358372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 8368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 8378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 8388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 8398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 840d4204758f77acb5a371fa1487a755b76a05d5476plougher block->size = i == file_end ? inode->data & (block_size - 1) : 841d4204758f77acb5a371fa1487a755b76a05d5476plougher block_size; 8428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block_list[i] == 0) /* sparse file */ 8438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 8448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 845d4204758f77acb5a371fa1487a755b76a05d5476plougher block->buffer = cache_get(data_cache, start, 846d4204758f77acb5a371fa1487a755b76a05d5476plougher block_list[i]); 8478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 848443c15812032991c98b33b5424b17bcd55fe3575plougher } 8498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 850443c15812032991c98b33b5424b17bcd55fe3575plougher } 851443c15812032991c98b33b5424b17bcd55fe3575plougher 85279df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 8538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 8548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 8558372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 8568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 8578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 8588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 85979df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 8608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 86179df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 86279df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 8638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 864b9cee889506e674726856035dba52d5e1cceeb99plougher } 865b9cee889506e674726856035dba52d5e1cceeb99plougher 866b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 867443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 868443c15812032991c98b33b5424b17bcd55fe3575plougher} 869476dcb48b24efff22caa970f000e151f1b28918dplougher 870476dcb48b24efff22caa970f000e151f1b28918dplougher 8716f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 872443c15812032991c98b33b5424b17bcd55fe3575plougher{ 8736f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 874443c15812032991c98b33b5424b17bcd55fe3575plougher 8756f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 876443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 8776013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 8786013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 8796013a30bd39550decc2546a47e5168e57bfcfde8plougher 8806f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 881c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create hardlink, " 882c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", strerror(errno)); 883443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 884443c15812032991c98b33b5424b17bcd55fe3575plougher } 885443c15812032991c98b33b5424b17bcd55fe3575plougher 886443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 887443c15812032991c98b33b5424b17bcd55fe3575plougher } 888443c15812032991c98b33b5424b17bcd55fe3575plougher 8896f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 8906f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 8916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 892c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("create_inode: regular file, file_size %lld, " 893c435240f52b78b0ef498118727ba8dad186db26bplougher "blocks %d\n", i->data, i->blocks); 894443c15812032991c98b33b5424b17bcd55fe3575plougher 89579df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 896443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 897443c15812032991c98b33b5424b17bcd55fe3575plougher break; 8986f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 89999ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSYMLINK_TYPE: 900d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: symlink, symlink_size %lld\n", 901d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data); 902443c15812032991c98b33b5424b17bcd55fe3575plougher 903a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 904a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 905a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 9066f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 907c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create symlink " 908c435240f52b78b0ef498118727ba8dad186db26bplougher "%s, because %s\n", pathname, 909c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 910443c15812032991c98b33b5424b17bcd55fe3575plougher break; 911443c15812032991c98b33b5424b17bcd55fe3575plougher } 912443c15812032991c98b33b5424b17bcd55fe3575plougher 9132ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, i->xattr); 9142ef25cb004cc6995bd36f781863aa844fe8c358dplougher 9159dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 9166f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 917c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to change " 918c435240f52b78b0ef498118727ba8dad186db26bplougher "uid and gids on %s, because " 919c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", pathname, 920c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 921443c15812032991c98b33b5424b17bcd55fe3575plougher } 922443c15812032991c98b33b5424b17bcd55fe3575plougher 923443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 924443c15812032991c98b33b5424b17bcd55fe3575plougher break; 925443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 92699ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_CHRDEV_TYPE: 92799ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LBLKDEV_TYPE: 92899ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LCHRDEV_TYPE: { 9296f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 930545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 931443c15812032991c98b33b5424b17bcd55fe3575plougher 9329dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 933a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 934a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 935a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 9366f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 937d4204758f77acb5a371fa1487a755b76a05d5476plougher makedev((i->data >> 8) & 0xff, 938d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data & 0xff)) == -1) { 939c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create " 940c435240f52b78b0ef498118727ba8dad186db26bplougher "%s device %s, because %s\n", 941d4204758f77acb5a371fa1487a755b76a05d5476plougher chrdev ? "character" : "block", 942d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 943443c15812032991c98b33b5424b17bcd55fe3575plougher break; 944443c15812032991c98b33b5424b17bcd55fe3575plougher } 945c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, 946fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->gid, i->time, i->xattr, TRUE); 947443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 948443c15812032991c98b33b5424b17bcd55fe3575plougher } else 949c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: could not create %s " 950c435240f52b78b0ef498118727ba8dad186db26bplougher "device %s, because you're not " 951c435240f52b78b0ef498118727ba8dad186db26bplougher "superuser!\n", chrdev ? "character" : 952c435240f52b78b0ef498118727ba8dad186db26bplougher "block", pathname); 953443c15812032991c98b33b5424b17bcd55fe3575plougher break; 9546f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 955443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 95699ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LFIFO_TYPE: 957443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 958443c15812032991c98b33b5424b17bcd55fe3575plougher 959a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 960a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 961a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 962443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 963d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create fifo %s, " 964d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, 965d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 966443c15812032991c98b33b5424b17bcd55fe3575plougher break; 967443c15812032991c98b33b5424b17bcd55fe3575plougher } 968c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, i->gid, 969fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->time, i->xattr, TRUE); 970443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 971443c15812032991c98b33b5424b17bcd55fe3575plougher break; 972443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 97399ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSOCKET_TYPE: 974443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 975443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 976443c15812032991c98b33b5424b17bcd55fe3575plougher break; 977443c15812032991c98b33b5424b17bcd55fe3575plougher default: 978d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Unknown inode type %d in create_inode_table!\n", 979d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type); 980443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 981443c15812032991c98b33b5424b17bcd55fe3575plougher } 982fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 9836f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 984443c15812032991c98b33b5424b17bcd55fe3575plougher 985443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 986443c15812032991c98b33b5424b17bcd55fe3575plougher} 987443c15812032991c98b33b5424b17bcd55fe3575plougher 988443c15812032991c98b33b5424b17bcd55fe3575plougher 98902bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_directory_table(long long start, long long end) 990443c15812032991c98b33b5424b17bcd55fe3575plougher{ 991443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 992443c15812032991c98b33b5424b17bcd55fe3575plougher 99341da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); 99441da3230b2ac91a73f9190676f66b3d80b21c270plougher 995443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 99607d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 99707d4d0dcafeb198a568f859b88034637e6e7a8e7plougher directory_table = realloc(directory_table, size += 99807d4d0dcafeb198a568f859b88034637e6e7a8e7plougher SQUASHFS_METADATA_SIZE); 99907d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(directory_table == NULL) 100007d4d0dcafeb198a568f859b88034637e6e7a8e7plougher EXIT_UNSQUASH("Out of memory in " 100107d4d0dcafeb198a568f859b88034637e6e7a8e7plougher "uncompress_directory_table\n"); 100207d4d0dcafeb198a568f859b88034637e6e7a8e7plougher } 1003c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("uncompress_directory_table: reading block 0x%llx\n", 1004c435240f52b78b0ef498118727ba8dad186db26bplougher start); 1005443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 1006176b325add10f6b9846f771f75d8543364d4c121plougher res = read_block(fd, start, &start, directory_table + bytes); 1007c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) 1008c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("uncompress_directory_table: failed to " 1009c435240f52b78b0ef498118727ba8dad186db26bplougher "read block\n"); 1010443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 1011443c15812032991c98b33b5424b17bcd55fe3575plougher } 1012443c15812032991c98b33b5424b17bcd55fe3575plougher} 1013443c15812032991c98b33b5424b17bcd55fe3575plougher 1014443c15812032991c98b33b5424b17bcd55fe3575plougher 10159dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 10169dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1017443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1018443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1019443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1020443c15812032991c98b33b5424b17bcd55fe3575plougher 1021443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1022443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1023443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1024443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1025443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1026443c15812032991c98b33b5424b17bcd55fe3575plougher 1027443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1028443c15812032991c98b33b5424b17bcd55fe3575plougher} 1029443c15812032991c98b33b5424b17bcd55fe3575plougher 1030443c15812032991c98b33b5424b17bcd55fe3575plougher 1031443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1032443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1033443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1034443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1035443c15812032991c98b33b5424b17bcd55fe3575plougher} 1036443c15812032991c98b33b5424b17bcd55fe3575plougher 1037443c15812032991c98b33b5424b17bcd55fe3575plougher 1038b54566f5c433764830c29c83151691d0034de094plougherchar *get_component(char *target, char *targname) 1039b54566f5c433764830c29c83151691d0034de094plougher{ 1040b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 10413cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1042b54566f5c433764830c29c83151691d0034de094plougher 1043b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 1044b54566f5c433764830c29c83151691d0034de094plougher *targname ++ = *target ++; 1045b54566f5c433764830c29c83151691d0034de094plougher 1046b54566f5c433764830c29c83151691d0034de094plougher *targname = '\0'; 1047b54566f5c433764830c29c83151691d0034de094plougher 1048b54566f5c433764830c29c83151691d0034de094plougher return target; 1049b54566f5c433764830c29c83151691d0034de094plougher} 1050b54566f5c433764830c29c83151691d0034de094plougher 1051b54566f5c433764830c29c83151691d0034de094plougher 10526ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 10536ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 10546ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 10556ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10566ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 10576ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 10586ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 10596ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 10606ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 10616ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 10626ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 10636ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 10646ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 10656ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10666ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 10676ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 10686ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10696ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10704dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1071b54566f5c433764830c29c83151691d0034de094plougher{ 107271add234b27054974d5e29f95b3fab3072792a62plougher char targname[1024]; 10734dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 107471add234b27054974d5e29f95b3fab3072792a62plougher 1075b7bb000643cd21c615a0366a7365441aa9c433f2plougher TRACE("add_path: adding \"%s\" extract file\n", target); 1076b7bb000643cd21c615a0366a7365441aa9c433f2plougher 107771add234b27054974d5e29f95b3fab3072792a62plougher target = get_component(target, targname); 107871add234b27054974d5e29f95b3fab3072792a62plougher 107971add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 10809dd4507fac1c96098eda8abe699a813a59451633plougher paths = malloc(sizeof(struct pathname)); 10819dd4507fac1c96098eda8abe699a813a59451633plougher if(paths == NULL) 10824dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 10834dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 108471add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 108571add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 108671add234b27054974d5e29f95b3fab3072792a62plougher } 108771add234b27054974d5e29f95b3fab3072792a62plougher 108871add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 108971add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 109071add234b27054974d5e29f95b3fab3072792a62plougher break; 109171add234b27054974d5e29f95b3fab3072792a62plougher 10926ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 1093d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1094d4204758f77acb5a371fa1487a755b76a05d5476plougher * allocate new name entry 1095d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 109671add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 1097d4204758f77acb5a371fa1487a755b76a05d5476plougher paths->name = realloc(paths->name, (i + 1) * 1098d4204758f77acb5a371fa1487a755b76a05d5476plougher sizeof(struct path_entry)); 1099fd628227871aecb36bb2b4f9c7f664f731510cdeplougher if(paths->name == NULL) 1100fd628227871aecb36bb2b4f9c7f664f731510cdeplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 110171add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].name = strdup(targname); 11026ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 11034dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 11044dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 11051f3cc42a2f77966d321a38d1709eba26f71104bdplougher if(paths->name[i].preg == NULL) 11061f3cc42a2f77966d321a38d1709eba26f71104bdplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 1107d4204758f77acb5a371fa1487a755b76a05d5476plougher error = regcomp(paths->name[i].preg, targname, 1108d4204758f77acb5a371fa1487a755b76a05d5476plougher REG_EXTENDED|REG_NOSUB); 1109545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 11104dba330d7b952f2f044d38e342e2ae3ea78910d6plougher char str[1024]; 11114dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 11124dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 1113d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("invalid regex %s in export %s, " 1114c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", targname, alltarget, 1115c435240f52b78b0ef498118727ba8dad186db26bplougher str); 11164dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 11174dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 11184dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 11196ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11206ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 1121d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1122d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component 1123d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 112471add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 112571add234b27054974d5e29f95b3fab3072792a62plougher else 1126d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1127d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1128d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11294dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 11306ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 1131d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1132d4204758f77acb5a371fa1487a755b76a05d5476plougher * existing matching entry 1133d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11346ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 1135d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1136c435240f52b78b0ef498118727ba8dad186db26bplougher * No sub-directory which means this is the leaf 1137c435240f52b78b0ef498118727ba8dad186db26bplougher * component of a pre-existing extract which subsumes 1138c435240f52b78b0ef498118727ba8dad186db26bplougher * the extract currently being added, in which case stop 1139c435240f52b78b0ef498118727ba8dad186db26bplougher * adding components 1140d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11416ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 1142d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1143d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component and child components exist 1144c435240f52b78b0ef498118727ba8dad186db26bplougher * from more specific extracts, delete as they're 1145c435240f52b78b0ef498118727ba8dad186db26bplougher * subsumed by this extract 1146d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11476ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 11486ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 11496ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 1150d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1151d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1152d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11536ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 115471add234b27054974d5e29f95b3fab3072792a62plougher } 115571add234b27054974d5e29f95b3fab3072792a62plougher 115671add234b27054974d5e29f95b3fab3072792a62plougher return paths; 115771add234b27054974d5e29f95b3fab3072792a62plougher} 11586ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11596ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1160a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 116171add234b27054974d5e29f95b3fab3072792a62plougher{ 11628372232d2460411adaa2299c32a0a88665e44902plougher struct pathnames *new = malloc(sizeof(struct pathnames)); 1163c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher if(new == NULL) 1164c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher EXIT_UNSQUASH("Out of memory in init_subdir\n"); 1165a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1166a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1167a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1168a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1169a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1170a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1171a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 11723488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths->count % PATHS_ALLOC_SIZE == 0) { 1173d4204758f77acb5a371fa1487a755b76a05d5476plougher paths = realloc(paths, sizeof(struct pathnames *) + 11743488d3bb3b89c394534ad2be909b661771a9581bplougher (paths->count + PATHS_ALLOC_SIZE) * 11753488d3bb3b89c394534ad2be909b661771a9581bplougher sizeof(struct pathname *)); 11763488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths == NULL) 11773488d3bb3b89c394534ad2be909b661771a9581bplougher EXIT_UNSQUASH("Out of memory in add_subdir\n"); 11783488d3bb3b89c394534ad2be909b661771a9581bplougher } 1179a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1180a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1181a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1182a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1183a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1184a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1185a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1186a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1187a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1188a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1189a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1190a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1191a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1192a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1193a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 119471add234b27054974d5e29f95b3fab3072792a62plougher 119571add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 119671add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1197b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 119871add234b27054974d5e29f95b3fab3072792a62plougher } 119971add234b27054974d5e29f95b3fab3072792a62plougher 1200a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1201a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1202a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1203a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1204a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1205a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1206c435240f52b78b0ef498118727ba8dad186db26bplougher regexec(path->name[i].preg, name, (size_t) 0, 1207c435240f52b78b0ef498118727ba8dad186db26bplougher NULL, 0) == 0 : fnmatch(path->name[i].name, 1208c435240f52b78b0ef498118727ba8dad186db26bplougher name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 1209c435240f52b78b0ef498118727ba8dad186db26bplougher 0; 1210a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1211d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1212d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a leaf component, any subdirectories 1213c435240f52b78b0ef498118727ba8dad186db26bplougher * will implicitly match, therefore return an 1214c435240f52b78b0ef498118727ba8dad186db26bplougher * empty new search set 1215d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1216a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1217a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1218a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1219d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1220d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a non-leaf component, add any 1221c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to the new set of 1222c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to scan for this name 1223d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1224a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1225a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1226a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1227b54566f5c433764830c29c83151691d0034de094plougher 1228a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1229d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1230d4204758f77acb5a371fa1487a755b76a05d5476plougher * no matching names found, delete empty search set, and return 1231d4204758f77acb5a371fa1487a755b76a05d5476plougher * FALSE 1232d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1233a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1234a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1235a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1236a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1237a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1238d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 12390a0d045642e8e413f90b770539193d3fd1522786plougher * one or more matches with sub-directories found (no leaf matches), 12400a0d045642e8e413f90b770539193d3fd1522786plougher * return new search set and return TRUE 12410a0d045642e8e413f90b770539193d3fd1522786plougher */ 1242a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1243a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1244a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 1245d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1246d4204758f77acb5a371fa1487a755b76a05d5476plougher * found matching leaf exclude, return empty search set and return TRUE 1247d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1248a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1249a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1250a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1251b54566f5c433764830c29c83151691d0034de094plougher} 1252b54566f5c433764830c29c83151691d0034de094plougher 1253b54566f5c433764830c29c83151691d0034de094plougher 1254b807ab3497c01a49fed6f9daafce3bfc599a9421ploughervoid pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1255d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1256eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1257eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 1258eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char *name, pathname[1024]; 1259eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 1260eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1261eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1262eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1263cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) 1264cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1265cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1266eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1267eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1268eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1269d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", 1270d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1271eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1272eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 1273eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1274eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1275eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 1276eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1277eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 1278eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 1279eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 1280d4204758f77acb5a371fa1487a755b76a05d5476plougher if(type == SQUASHFS_FILE_TYPE || 1281d4204758f77acb5a371fa1487a755b76a05d5476plougher type == SQUASHFS_LREG_TYPE) { 1282312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 1283eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 1284d4204758f77acb5a371fa1487a755b76a05d5476plougher created_inode[i->inode_number - 1] = 1285d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) i; 1286d4204758f77acb5a371fa1487a755b76a05d5476plougher total_blocks += (i->data + 1287d4204758f77acb5a371fa1487a755b76a05d5476plougher (block_size - 1)) >> block_log; 1288eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1289eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 1290eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1291eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 1292eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1293eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1294eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 1295eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1296eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1297eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 1298eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1299eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1300eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1301a2cff53655359b044ea88baa76cb16d1c8f44d2aploughervoid dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1302d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1303443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1304443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1305443c15812032991c98b33b5424b17bcd55fe3575plougher char *name, pathname[1024]; 1306a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 1307eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1308eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1309443c15812032991c98b33b5424b17bcd55fe3575plougher 1310cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) { 1311cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher ERROR("dir_scan: failed to read directory %s, skipping\n", 1312cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher parent_name); 1313cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1314cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher } 1315cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1316eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 1317eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 1318eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1319d4204758f77acb5a371fa1487a755b76a05d5476plougher if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && 132085917a285edbd4bb78f1b245f66c634d1e0d4029plougher (!force || errno != EEXIST)) { 132185917a285edbd4bb78f1b245f66c634d1e0d4029plougher ERROR("dir_scan: failed to make directory %s, because %s\n", 1322d4204758f77acb5a371fa1487a755b76a05d5476plougher parent_name, strerror(errno)); 132385917a285edbd4bb78f1b245f66c634d1e0d4029plougher squashfs_closedir(dir); 132485917a285edbd4bb78f1b245f66c634d1e0d4029plougher return; 132585917a285edbd4bb78f1b245f66c634d1e0d4029plougher } 1326443c15812032991c98b33b5424b17bcd55fe3575plougher 1327443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1328d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", 1329d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1330b54566f5c433764830c29c83151691d0034de094plougher 133171add234b27054974d5e29f95b3fab3072792a62plougher 133271add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 1333b54566f5c433764830c29c83151691d0034de094plougher continue; 1334b54566f5c433764830c29c83151691d0034de094plougher 1335443c15812032991c98b33b5424b17bcd55fe3575plougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 1336fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1337443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 133871add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 1339a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher else if(new == NULL) { 1340312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 13416f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 13426f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 13436f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 13446f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1345eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!lsonly) { 13466f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 1347eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher update_progress_bar(); 1348eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1349427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher 1350d4204758f77acb5a371fa1487a755b76a05d5476plougher if(i->type == SQUASHFS_SYMLINK_TYPE || 1351d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type == SQUASHFS_LSYMLINK_TYPE) 1352427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher free(i->symlink); 13536f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1354a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1355a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 1356443c15812032991c98b33b5424b17bcd55fe3575plougher } 1357443c15812032991c98b33b5424b17bcd55fe3575plougher 1358074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 1359d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(parent_name, dir->mode, dir->uid, dir->guid, 1360fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher dir->mtime, dir->xattr, force); 1361443c15812032991c98b33b5424b17bcd55fe3575plougher 1362443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 1363443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 1364443c15812032991c98b33b5424b17bcd55fe3575plougher} 1365443c15812032991c98b33b5424b17bcd55fe3575plougher 1366443c15812032991c98b33b5424b17bcd55fe3575plougher 1367b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 1368b624936abba03d38b7e9245c647339d8f6f34274plougher{ 136927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher time_t mkfs_time = (time_t) sBlk.s.mkfs_time; 1370b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 1371b624936abba03d38b7e9245c647339d8f6f34274plougher 1372b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 1373d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 137427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "little endian " : 137527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1376b624936abba03d38b7e9245c647339d8f6f34274plougher#else 1377d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 137827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "big endian " : 137927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1380b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 1381c766500607f1ea7494b8360409be3d8ea66f9761plougher 1382d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : 1383d4204758f77acb5a371fa1487a755b76a05d5476plougher "failed to get time\n"); 1384e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", 1385e3206fad5b70e7e0527db2a627ad26616a8a2429plougher sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / 1386e3206fad5b70e7e0527db2a627ad26616a8a2429plougher (1024.0 * 1024.0)); 1387c766500607f1ea7494b8360409be3d8ea66f9761plougher 138827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 1389e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Compression %s\n", comp->name); 1390c766500607f1ea7494b8360409be3d8ea66f9761plougher 139127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Block size %d\n", sBlk.s.block_size); 1392d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem is %sexportable via NFS\n", 139327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); 1394d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Inodes are %scompressed\n", 139527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); 1396d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Data is %scompressed\n", 139727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); 1398c766500607f1ea7494b8360409be3d8ea66f9761plougher 13997ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(sBlk.s.s_major > 1) { 14007ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) 14017ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are not stored\n"); 14027ca09d1320cdc30a068f179b93ca5c141b55c395plougher else { 14037ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are %scompressed\n", 14047ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? 14057ca09d1320cdc30a068f179b93ca5c141b55c395plougher "un" : ""); 14067ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Always_use_fragments option is %sspecified\n", 14077ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : 14087ca09d1320cdc30a068f179b93ca5c141b55c395plougher "not "); 14097ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 14107ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 14117ca09d1320cdc30a068f179b93ca5c141b55c395plougher 1412de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(sBlk.s.s_major == 4) { 1413de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) 1414de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are not stored\n"); 1415de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher else 1416de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are %scompressed\n", 1417de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? 1418de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher "un" : ""); 1419de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher } 1420de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher 1421ba95dd35ef0e9f618d926ddc1a595076adc23818plougher if(sBlk.s.s_major < 4) 1422ba95dd35ef0e9f618d926ddc1a595076adc23818plougher printf("Check data is %spresent in the filesystem\n", 1423ba95dd35ef0e9f618d926ddc1a595076adc23818plougher SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : 1424ba95dd35ef0e9f618d926ddc1a595076adc23818plougher "not "); 1425c766500607f1ea7494b8360409be3d8ea66f9761plougher 142627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 1427d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Duplicates are %sremoved\n", 142827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); 14290337de3977eec74e6a3d28e0d0863299246de8b7plougher else 14300337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 1431c766500607f1ea7494b8360409be3d8ea66f9761plougher 143227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 143327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of fragments %d\n", sBlk.s.fragments); 1434c766500607f1ea7494b8360409be3d8ea66f9761plougher 143527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of inodes %d\n", sBlk.s.inodes); 1436c766500607f1ea7494b8360409be3d8ea66f9761plougher 143727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 143827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of ids %d\n", sBlk.s.no_ids); 14390f74340e3b68533339adc60f418ddf59fa188f61plougher else { 14400f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of uids %d\n", sBlk.no_uids); 14410f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of gids %d\n", sBlk.no_guids); 14420f74340e3b68533339adc60f418ddf59fa188f61plougher } 1443b624936abba03d38b7e9245c647339d8f6f34274plougher 144427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); 144527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.directory_table_start 0x%llx\n", 144627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 1447c766500607f1ea7494b8360409be3d8ea66f9761plougher 14480ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 1) 14490ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", 14500ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.fragment_table_start); 14510ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 14520ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 2) 14530ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.lookup_table_start 0x%llx\n\n", 14540ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.lookup_table_start); 14550ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 1456053da34003852e494400c1ade35b526e1821b576plougher if(sBlk.s.s_major == 4) { 145727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); 1458053da34003852e494400c1ade35b526e1821b576plougher TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", 1459053da34003852e494400c1ade35b526e1821b576plougher sBlk.s.xattr_id_table_start); 1460053da34003852e494400c1ade35b526e1821b576plougher } else { 14610f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 14620f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); 14630f74340e3b68533339adc60f418ddf59fa188f61plougher } 1464b624936abba03d38b7e9245c647339d8f6f34274plougher} 1465b624936abba03d38b7e9245c647339d8f6f34274plougher 1466b624936abba03d38b7e9245c647339d8f6f34274plougher 146702bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 1468443c15812032991c98b33b5424b17bcd55fe3575plougher{ 14696490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block_3 sBlk_3; 147064e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher struct squashfs_super_block sBlk_4; 14716490378e5b5e8dc058daf28423a7465699a6ba7bplougher 14726490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 14736490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Try to read a Squashfs 4 superblock 14746490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 147564e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), 14763306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_4); 147754660e177ba40ab08ee2f3304b9f030eb5675677plougher swap = sBlk_4.s_magic != SQUASHFS_MAGIC; 14786490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); 14796490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1480d4204758f77acb5a371fa1487a755b76a05d5476plougher if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && 1481d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk_4.s_minor == 0) { 14826490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.squashfs_opendir = squashfs_opendir_4; 14836490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment = read_fragment_4; 14846490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment_table = read_fragment_table_4; 14856490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_block_list = read_block_list_2; 14866490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_inode = read_inode_4; 14876490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_uids_guids = read_uids_guids_4; 14886490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); 1489efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1490efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 1491efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher * Check the compression type 1492efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 149327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher comp = lookup_compressor_id(sBlk.s.compression); 14946490378e5b5e8dc058daf28423a7465699a6ba7bplougher return TRUE; 14956490378e5b5e8dc058daf28423a7465699a6ba7bplougher } 14966490378e5b5e8dc058daf28423a7465699a6ba7bplougher 14976490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 14986490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock 14996490378e5b5e8dc058daf28423a7465699a6ba7bplougher * (compatible with 1 and 2 filesystems) 15006490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 150186561909d9ca51a4e4ce4efcfea30b41d1d08275plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), 15023306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_3); 1503443c15812032991c98b33b5424b17bcd55fe3575plougher 1504d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1505d4204758f77acb5a371fa1487a755b76a05d5476plougher * Check it is a SQUASHFS superblock 1506d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1507443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 150821ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic != SQUASHFS_MAGIC) { 150921ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { 15107a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher squashfs_super_block_3 sblk; 1511c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Reading a different endian SQUASHFS filesystem " 1512c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s\n", source); 15136490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); 15146490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); 1515443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 1516443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 1517c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Can't find a SQUASHFS superblock on %s\n", 1518c435240f52b78b0ef498118727ba8dad186db26bplougher source); 1519443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1520443c15812032991c98b33b5424b17bcd55fe3575plougher } 1521443c15812032991c98b33b5424b17bcd55fe3575plougher } 1522443c15812032991c98b33b5424b17bcd55fe3575plougher 152327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_magic = sBlk_3.s_magic; 152427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inodes = sBlk_3.inodes; 152527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.mkfs_time = sBlk_3.mkfs_time; 152627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size; 152727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragments = sBlk_3.fragments; 152827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_log = sBlk_3.block_log; 152927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.flags = sBlk_3.flags; 153027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major = sBlk_3.s_major; 153127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor = sBlk_3.s_minor; 153227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.root_inode = sBlk_3.root_inode; 153327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used; 153427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start; 153527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start; 153627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; 153727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; 15386490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_uids = sBlk_3.no_uids; 15396490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_guids = sBlk_3.no_guids; 15406490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start; 15416490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start; 154227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 15436490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1544443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 154527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { 154627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used_2; 15476490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start_2; 15486490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start_2; 154927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; 155027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; 155102bc3bcabf2b219f63961f07293b83629948f026plougher 155227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1) { 155327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size_1; 155427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk.uid_start; 1555ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1556ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 1557ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 15586f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 155979e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1560ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 156127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = 1562c435240f52b78b0ef498118727ba8dad186db26bplougher sBlk_3.fragment_table_start_2; 1563ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1564ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 1565ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 1566ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 15676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 156879e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1569ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 157027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher } else if(sBlk.s.s_major == 3) { 1571ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_3; 1572ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment = read_fragment_3; 1573ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment_table = read_fragment_table_3; 1574ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 1575ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_inode = read_inode_3; 157679e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 157702bc3bcabf2b219f63961f07293b83629948f026plougher } else { 157827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, 157927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor); 15804c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 1581443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1582443c15812032991c98b33b5424b17bcd55fe3575plougher } 1583443c15812032991c98b33b5424b17bcd55fe3575plougher 1584efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 158599c8abf4de4297b3159355a0cefe9ad6f5182827plougher * 1.x, 2.x and 3.x filesystems use gzip compression. 1586efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 1587efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp = lookup_compressor("gzip"); 1588443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1589443c15812032991c98b33b5424b17bcd55fe3575plougher 1590443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 1591443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1592443c15812032991c98b33b5424b17bcd55fe3575plougher} 1593443c15812032991c98b33b5424b17bcd55fe3575plougher 1594443c15812032991c98b33b5424b17bcd55fe3575plougher 1595a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 159671add234b27054974d5e29f95b3fab3072792a62plougher{ 159771add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 159871add234b27054974d5e29f95b3fab3072792a62plougher char name[16384]; 159971add234b27054974d5e29f95b3fab3072792a62plougher 160063e21ee4b795bb900f82c18e7b5c6f7369907360plougher fd = fopen(filename, "r"); 160163e21ee4b795bb900f82c18e7b5c6f7369907360plougher if(fd == NULL) 1602d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("Could not open %s, because %s\n", filename, 1603d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 160471add234b27054974d5e29f95b3fab3072792a62plougher 160571add234b27054974d5e29f95b3fab3072792a62plougher while(fscanf(fd, "%16384[^\n]\n", name) != EOF) 1606a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 160771add234b27054974d5e29f95b3fab3072792a62plougher 160871add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 1609a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 161071add234b27054974d5e29f95b3fab3072792a62plougher} 161171add234b27054974d5e29f95b3fab3072792a62plougher 161271add234b27054974d5e29f95b3fab3072792a62plougher 1613d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1614d4204758f77acb5a371fa1487a755b76a05d5476plougher * reader thread. This thread processes read requests queued by the 1615d4204758f77acb5a371fa1487a755b76a05d5476plougher * cache_get() routine. 1616d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 16178888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 16188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 16198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 16208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 162186561909d9ca51a4e4ce4efcfea30b41d1d08275plougher int res = read_fs_bytes(fd, entry->block, 16228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 16238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 16248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 1626d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1627c435240f52b78b0ef498118727ba8dad186db26bplougher * queue successfully read block to the deflate 1628c435240f52b78b0ef498118727ba8dad186db26bplougher * thread(s) for further processing 1629d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 16308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_deflate, entry); 16318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1632d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1633d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has either been successfully read and is 1634d4204758f77acb5a371fa1487a755b76a05d5476plougher * uncompressed, or an error has occurred, clear pending 1635c435240f52b78b0ef498118727ba8dad186db26bplougher * flag, set error appropriately, and wake up any 1636c435240f52b78b0ef498118727ba8dad186db26bplougher * threads waiting on this buffer 1637d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 16388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 16398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 16418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1643d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1644d4204758f77acb5a371fa1487a755b76a05d5476plougher * writer thread. This processes file write requests queued by the 1645d4204758f77acb5a371fa1487a755b76a05d5476plougher * write_file() routine. 1646d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 16478888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 16488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 16498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 16508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 16528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 16538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 165487f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougher long long hole = 0; 165527636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 1656c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error; 16578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 16598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 16608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 16618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 16648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 16668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1667eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 16688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 16698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 16718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 16728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 16738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 16748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 167727636cb2cec37a68313f9eb825c0548245eecad0plougher 167827636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 167927636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 168027636cb2cec37a68313f9eb825c0548245eecad0plougher 1681c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(failed) 1682c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher continue; 1683c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1684c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher error = write_block(file_fd, block->buffer->data + 1685c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher block->offset, block->size, hole, file->sparse); 1686c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1687c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == FALSE) { 1688d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write data block %d\n", 1689d4204758f77acb5a371fa1487a755b76a05d5476plougher i); 169027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 16918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 1692c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 16938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 16948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 16958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 16968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 169827636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 1699d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1700d4204758f77acb5a371fa1487a755b76a05d5476plougher * corner case for hole extending to end of file 1701d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1702d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file->sparse == FALSE || 1703d4204758f77acb5a371fa1487a755b76a05d5476plougher lseek(file_fd, hole, SEEK_CUR) == -1) { 1704d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1705d4204758f77acb5a371fa1487a755b76a05d5476plougher * for files which we don't want to write 1706c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * sparsely, or for broken lseeks which cannot 1707c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * seek beyond end of file, write_block will do 1708c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * the right thing 1709c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher */ 17108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 1711d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_block(file_fd, "\0", 1, hole, 1712d4204758f77acb5a371fa1487a755b76a05d5476plougher file->sparse) == FALSE) { 1713d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse " 1714d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 171527636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 17168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 1718d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse data " 1719d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 172027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 17218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher close(file_fd); 172527636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 1726d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(file->pathname, file->mode, file->uid, 1727fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher file->gid, file->time, file->xattr, force); 172827636cb2cec37a68313f9eb825c0548245eecad0plougher else { 172927636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 173027636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 173127636cb2cec37a68313f9eb825c0548245eecad0plougher } 173279df93becb68081effabebba3006c794be308598plougher free(file->pathname); 17338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 173427636cb2cec37a68313f9eb825c0548245eecad0plougher 17358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 17378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1739d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1740d4204758f77acb5a371fa1487a755b76a05d5476plougher * decompress thread. This decompresses buffers queued by the read thread 1741d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 17428888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *deflator(void *arg) 17438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 17448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 17458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 17478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_deflate); 1748efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 1749efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1750b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, tmp, entry->data, 1751efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, 1752efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher &error); 1753efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1754efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) 1755efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 1756efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 1757efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher else 1758efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher memcpy(entry->data, tmp, res); 17598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1760d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1761d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has been either successfully decompressed, or an error 17628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 1763d4204758f77acb5a371fa1487a755b76a05d5476plougher * wake up any threads waiting on this block 1764d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1765efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher cache_block_ready(entry, res == -1); 17668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 17688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1770eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 1771eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1772eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timeval timeval; 1773eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timespec timespec; 17741b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 17751b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 17761b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 17771b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 177801b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher if(isatty(STDOUT_FILENO)) 177901b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 178001b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher "columns\n"); 17811b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 17821b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 17831b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 17841b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 17851b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 17861b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 17871b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 17881b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 17891b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 17901b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 17911b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 1792eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1793eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_init(&progress_wait, NULL); 1794eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 17951b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 1796eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 1797eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher gettimeofday(&timeval, NULL); 1798eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec = timeval.tv_sec; 1799eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(timeval.tv_usec + 250000 > 999999) 1800eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec++; 1801c435240f52b78b0ef498118727ba8dad186db26bplougher timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1802c435240f52b78b0ef498118727ba8dad186db26bplougher 1000; 1803c435240f52b78b0ef498118727ba8dad186db26bplougher pthread_cond_timedwait(&progress_wait, &screen_mutex, 1804c435240f52b78b0ef498118727ba8dad186db26bplougher ×pec); 18051b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress_enabled) 18061b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 1807d4204758f77acb5a371fa1487a755b76a05d5476plougher fifo_count + cur_blocks, total_inodes - 1808d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks, columns); 1809eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1810eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1811eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1812eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 18138888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 18148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 18158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 18168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 18178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int all_buffers_size = fragment_buffer_size + data_buffer_size; 18188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 18208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGINT); 18218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 18228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 1823c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 1824c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 18258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 18278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 18288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 18298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 18308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 18328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 18338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 18348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 18358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 18368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 18378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 1839d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Failed to get number of available processors. " 1840d4204758f77acb5a371fa1487a755b76a05d5476plougher "Defaulting to 1\n"); 18418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 18428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 18449cc26b77a61fefdeb45f5c487c2bfdefd394b66fplougher processors = sysconf(_SC_NPROCESSORS_ONLN); 18458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 18468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18486697cff2155192a3e0c182a3cef046ebf215ac32plougher thread = malloc((3 + processors) * sizeof(pthread_t)); 18496697cff2155192a3e0c182a3cef046ebf215ac32plougher if(thread == NULL) 18508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 1851eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher deflator_thread = &thread[3]; 18528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_reader = queue_init(all_buffers_size); 18548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_deflate = queue_init(all_buffers_size); 1855eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher to_writer = queue_init(1000); 18568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 18578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 18588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 18598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 18608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 1861eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 18628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 18638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 1865c435240f52b78b0ef498118727ba8dad186db26bplougher if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 1866c435240f52b78b0ef498118727ba8dad186db26bplougher 0) 18678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 18688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 18718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 18728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) 1874c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 1875c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 18768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 18778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18791b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 18801b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 18811b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 18821b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = TRUE; 18831b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 18841b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 18851b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18861b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18871b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 18881b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 18891b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 18901b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 18911b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 18921b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 18931b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18941b42101056befe25b5f19d5b099e806a2ecee9cdplougher 1895eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar() 1896eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 18971b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 1898eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_signal(&progress_wait); 18991b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 1900eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1901eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1902eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1903eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 1904eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1905eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 1906b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher int max_digits, used, hashes, spaces; 1907dce832998340bea4236fddb5ba1525121044ce18plougher static int tty = -1; 1908eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1909b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher if(max == 0) 1910b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher return; 1911b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 1912b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher max_digits = floor(log10(max)) + 1; 1913b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher used = max_digits * 2 + 11; 1914b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher hashes = (current * (columns - used)) / max; 1915b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher spaces = columns - used - hashes; 1916b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 1917eaf639366792995c36ae7295bddf534f6f416643plougher if((current > max) || (columns - used < 0)) 1918eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 1919eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1920dce832998340bea4236fddb5ba1525121044ce18plougher if(tty == -1) 1921dce832998340bea4236fddb5ba1525121044ce18plougher tty = isatty(STDOUT_FILENO); 1922dce832998340bea4236fddb5ba1525121044ce18plougher if(!tty) { 1923dce832998340bea4236fddb5ba1525121044ce18plougher static long long previous = -1; 1924dce832998340bea4236fddb5ba1525121044ce18plougher 19250a0d045642e8e413f90b770539193d3fd1522786plougher /* 19260a0d045642e8e413f90b770539193d3fd1522786plougher * Updating much more frequently than this results in huge 19270a0d045642e8e413f90b770539193d3fd1522786plougher * log files. 19280a0d045642e8e413f90b770539193d3fd1522786plougher */ 1929dce832998340bea4236fddb5ba1525121044ce18plougher if((current % 100) != 0 && current != max) 1930dce832998340bea4236fddb5ba1525121044ce18plougher return; 1931dce832998340bea4236fddb5ba1525121044ce18plougher /* Don't update just to rotate the spinner. */ 1932dce832998340bea4236fddb5ba1525121044ce18plougher if(current == previous) 1933dce832998340bea4236fddb5ba1525121044ce18plougher return; 1934dce832998340bea4236fddb5ba1525121044ce18plougher previous = current; 1935dce832998340bea4236fddb5ba1525121044ce18plougher } 1936dce832998340bea4236fddb5ba1525121044ce18plougher 1937eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 1938eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1939eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 1940eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 1941eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1942eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 1943eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1944eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 1945eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 1946eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1947eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 1948eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 1949eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 1950eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1951eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1952eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1953443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 19540ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher printf("unsquashfs version 4.2-CVS (2012/01/12)\n");\ 19550ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher printf("copyright (C) 2012 Phillip Lougher "\ 1956e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "<phillip@lougher.demon.co.uk>\n\n");\ 1957e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is free software; you can redistribute it and/or"\ 1958d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1959e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("modify it under the terms of the GNU General Public License"\ 1960d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1961e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("as published by the Free Software Foundation; either version "\ 1962e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "2,\n");\ 1963e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("or (at your option) any later version.\n\n");\ 1964e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is distributed in the hope that it will be "\ 1965e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "useful,\n");\ 1966d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ 1967d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1968d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ 1969d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1970443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 1971443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 1972443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1973443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 1974b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 1975545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 1976a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 1977a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 1978ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 1979ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 19800cf5c297bec42c7c220d2825f12f9499f2293279plougher char *b; 1981443c15812032991c98b33b5424b17bcd55fe3575plougher 19821b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 1983545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 1984545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 19859dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 19869dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 1987443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 1988443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 1989443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1990d4204758f77acb5a371fa1487a755b76a05d5476plougher if(strcmp(argv[i], "-version") == 0 || 1991d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-v") == 0) { 1992443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 1993443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 1994d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-info") == 0 || 1995d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-i") == 0) 1996443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 1997c435240f52b78b0ef498118727ba8dad186db26bplougher else if(strcmp(argv[i], "-ls") == 0 || 1998c435240f52b78b0ef498118727ba8dad186db26bplougher strcmp(argv[i], "-l") == 0) 1999443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 2000d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-no-progress") == 0 || 2001d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-n") == 0) 2002296d7d8a68e33341d68f4354b5e1fe2f3aa275a6plougher progress = FALSE; 200331638061a6de0cb89093672aa71ddeb42f2eb28aplougher else if(strcmp(argv[i], "-no-xattrs") == 0 || 200431638061a6de0cb89093672aa71ddeb42f2eb28aplougher strcmp(argv[i], "-no") == 0) 200531638061a6de0cb89093672aa71ddeb42f2eb28aplougher no_xattrs = TRUE; 2006df9d38a515489c2c573754ad81abd230dfd8b1f0plougher else if(strcmp(argv[i], "-xattrs") == 0 || 2007df9d38a515489c2c573754ad81abd230dfd8b1f0plougher strcmp(argv[i], "-x") == 0) 2008df9d38a515489c2c573754ad81abd230dfd8b1f0plougher no_xattrs = FALSE; 2009d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-dest") == 0 || 2010d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-d") == 0) { 201171add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2012d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -dest missing filename\n", 2013d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 201471add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 201571add234b27054974d5e29f95b3fab3072792a62plougher } 2016443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 2017d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-processors") == 0 || 2018d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-p") == 0) { 2019c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 2020c435240f52b78b0ef498118727ba8dad186db26bplougher (processors = strtol(argv[i], &b, 10), 2021d4204758f77acb5a371fa1487a755b76a05d5476plougher *b != '\0')) { 2022d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors missing or invalid " 2023d4204758f77acb5a371fa1487a755b76a05d5476plougher "processor number\n", argv[0]); 20240cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 20250cf5c297bec42c7c220d2825f12f9499f2293279plougher } 20260cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 2027d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors should be 1 or larger\n", 2028d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 20290cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 20300cf5c297bec42c7c220d2825f12f9499f2293279plougher } 2031d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-data-queue") == 0 || 2032d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-da") == 0) { 2033c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 2034c435240f52b78b0ef498118727ba8dad186db26bplougher (data_buffer_size = strtol(argv[i], &b, 2035d4204758f77acb5a371fa1487a755b76a05d5476plougher 10), *b != '\0')) { 2036c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -data-queue missing or invalid " 2037c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2038ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2039ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2040ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 2041d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue should be 1 Mbyte or " 2042d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2043ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2044ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2045d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || 2046d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-fr") == 0) { 2047c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 2048c435240f52b78b0ef498118727ba8dad186db26bplougher (fragment_buffer_size = strtol(argv[i], 2049d4204758f77acb5a371fa1487a755b76a05d5476plougher &b, 10), *b != '\0')) { 2050c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -frag-queue missing or invalid " 2051c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2052ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2053ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2054ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 2055d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue should be 1 Mbyte or " 2056d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2057ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2058ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2059d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-force") == 0 || 2060d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-f") == 0) 2061a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 2062d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-stat") == 0 || 2063d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-s") == 0) 2064b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 2065d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-lls") == 0 || 2066d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-ll") == 0) { 20679baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 20689baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2069d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-linfo") == 0 || 2070d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-li") == 0) { 20719baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 20729baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2073d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-ef") == 0 || 2074d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-e") == 0) { 207571add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2076d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -ef missing filename\n", 2077d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 207871add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 207971add234b27054974d5e29f95b3fab3072792a62plougher } 2080a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 2081d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-regex") == 0 || 2082d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-r") == 0) 20834dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 20844dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2085b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2086443c15812032991c98b33b5424b17bcd55fe3575plougher } 2087443c15812032991c98b33b5424b17bcd55fe3575plougher 2088feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher if(lsonly || info) 2089feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher progress = FALSE; 2090feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher 2091bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#ifdef SQUASHFS_TRACE 2092bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher progress = FALSE; 2093bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#endif 2094bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher 2095443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2096443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2097443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 2098d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("SYNTAX: %s [options] filesystem [directories or " 2099d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract]\n", argv[0]); 2100d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-v[ersion]\t\tprint version, licence and " 2101d4204758f77acb5a371fa1487a755b76a05d5476plougher "copyright information\n"); 2102d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " 2103d4204758f77acb5a371fa1487a755b76a05d5476plougher "default \"squashfs-root\"\n"); 2104c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-n[o-progress]\t\tdon't display the progress " 2105c435240f52b78b0ef498118727ba8dad186db26bplougher "bar\n"); 2106df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" 2107df9d38a515489c2c573754ad81abd230dfd8b1f0plougher NOXOPT_STR"\n"); 2108df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-x[attrs]\t\textract xattrs in file system" 2109df9d38a515489c2c573754ad81abd230dfd8b1f0plougher XOPT_STR "\n"); 2110c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-p[rocessors] <number>\tuse <number> " 2111c435240f52b78b0ef498118727ba8dad186db26bplougher "processors. By default will use\n"); 2112c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tnumber of processors available\n"); 2113c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-i[nfo]\t\t\tprint files as they are " 2114c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed\n"); 2115c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-li[nfo]\t\tprint files as they are " 2116c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed with file\n"); 2117c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tattributes (like ls -l output)\n"); 2118d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" 2119d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2120c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-ll[s]\t\t\tlist filesystem with file " 2121c435240f52b78b0ef498118727ba8dad186db26bplougher "attributes (like\n"); 2122c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tls -l output), but don't unsquash\n"); 2123c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-f[orce]\t\tif file already exists then " 2124c435240f52b78b0ef498118727ba8dad186db26bplougher "overwrite\n"); 2125d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " 2126d4204758f77acb5a371fa1487a755b76a05d5476plougher "information\n"); 2127d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-e[f] <extract file>\tlist of directories or " 2128d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract.\n\t\t\t\tOne per line\n"); 2129c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-da[ta-queue] <size>\tSet data queue to " 2130c435240f52b78b0ef498118727ba8dad186db26bplougher "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", 2131d4204758f77acb5a371fa1487a755b76a05d5476plougher DATA_BUFFER_DEFAULT); 21328bc376ba1f7110fb88989e5134b74aa8412fb00eplougher ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " 2133d56f6723626a391b473c2c023b628abcd8ed31e3Phillip Lougher "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", 2134d4204758f77acb5a371fa1487a755b76a05d5476plougher FRAGMENT_BUFFER_DEFAULT); 2135c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX " 2136c435240f52b78b0ef498118727ba8dad186db26bplougher "regular expressions\n"); 2137c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\trather than use the default shell " 2138c435240f52b78b0ef498118727ba8dad186db26bplougher "wildcard\n\t\t\t\texpansion (globbing)\n"); 2139076b053e2cce5c9172b4f385e866c2e606712a32plougher ERROR("\nDecompressors available:\n"); 2140076b053e2cce5c9172b4f385e866c2e606712a32plougher display_compressors("", ""); 2141443c15812032991c98b33b5424b17bcd55fe3575plougher } 2142443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2143443c15812032991c98b33b5424b17bcd55fe3575plougher } 2144443c15812032991c98b33b5424b17bcd55fe3575plougher 214571add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2146a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2147b54566f5c433764830c29c83151691d0034de094plougher 2148443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2149d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Could not open %s, because %s\n", argv[i], 2150d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 2151443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2152443c15812032991c98b33b5424b17bcd55fe3575plougher } 2153443c15812032991c98b33b5424b17bcd55fe3575plougher 215402bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2155443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2156443c15812032991c98b33b5424b17bcd55fe3575plougher 2157b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2158b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2159b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2160b624936abba03d38b7e9245c647339d8f6f34274plougher } 2161b624936abba03d38b7e9245c647339d8f6f34274plougher 2162f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher if(!comp->supported) { 2163f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Filesystem uses %s compression, this is " 2164f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher "unsupported by this version\n", comp->name); 2165f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Decompressors available:\n"); 2166f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher display_compressors("", ""); 2167f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher exit(1); 2168f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher } 2169f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher 217027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_size = sBlk.s.block_size; 217127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_log = sBlk.s.block_log; 2172ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2173ae271cc93e3684d5314bcdc45b631e497ae43166plougher fragment_buffer_size <<= 20 - block_log; 2174ae271cc93e3684d5314bcdc45b631e497ae43166plougher data_buffer_size <<= 20 - block_log; 21758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 21768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 217744a6967088416c9bd6ee7165bde59c9ba5ccb704plougher fragment_data = malloc(block_size); 217844a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(fragment_data == NULL) 2179443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2180443c15812032991c98b33b5424b17bcd55fe3575plougher 218144a6967088416c9bd6ee7165bde59c9ba5ccb704plougher file_data = malloc(block_size); 218244a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(file_data == NULL) 2183443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2184443c15812032991c98b33b5424b17bcd55fe3575plougher 218544a6967088416c9bd6ee7165bde59c9ba5ccb704plougher data = malloc(block_size); 218644a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(data == NULL) 2187eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2188443c15812032991c98b33b5424b17bcd55fe3575plougher 218944a6967088416c9bd6ee7165bde59c9ba5ccb704plougher created_inode = malloc(sBlk.s.inodes * sizeof(char *)); 219044a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(created_inode == NULL) 2191443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2192443c15812032991c98b33b5424b17bcd55fe3575plougher 219327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 2194443c15812032991c98b33b5424b17bcd55fe3575plougher 21951a7e7e871169a6cb6e3470a50b33db83830886e2plougher if(s_ops.read_uids_guids() == FALSE) 21961a7e7e871169a6cb6e3470a50b33db83830886e2plougher EXIT_UNSQUASH("failed to uid/gid table\n"); 2197ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2198cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher if(s_ops.read_fragment_table() == FALSE) 2199cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher EXIT_UNSQUASH("failed to read fragment table\n"); 2200ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 220127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher uncompress_inode_table(sBlk.s.inode_table_start, 220227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 2203ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 220427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher uncompress_directory_table(sBlk.s.directory_table_start, 220527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start); 2206443c15812032991c98b33b5424b17bcd55fe3575plougher 220731638061a6de0cb89093672aa71ddeb42f2eb28aplougher if(no_xattrs) 220831638061a6de0cb89093672aa71ddeb42f2eb28aplougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 220931638061a6de0cb89093672aa71ddeb42f2eb28aplougher 22108935dc25479321709c74c2f8214cf5365669100eplougher if(read_xattrs_from_disk(fd, &sBlk.s) == 0) 22118935dc25479321709c74c2f8214cf5365669100eplougher EXIT_UNSQUASH("failed to read the xattr table\n"); 22128935dc25479321709c74c2f8214cf5365669100eplougher 2213a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2214a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2215a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2216a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2217a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 221827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 221927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2220eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 222127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 22229b58176e667b67770569c9076a410b27aaa3bcf5plougher inode_number = 1; 2223eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2224c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%d inodes (%d blocks) to write\n\n", total_inodes, 2225c435240f52b78b0ef498118727ba8dad186db26bplougher total_inodes - total_files + total_blocks); 2226eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 22271b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 22281b42101056befe25b5f19d5b099e806a2ecee9cdplougher enable_progress_bar(); 22291b42101056befe25b5f19d5b099e806a2ecee9cdplougher 223027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 223127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2232443c15812032991c98b33b5424b17bcd55fe3575plougher 22338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 22348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 22358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22365c7885bc293ab675812fd77a05f59c2917e3e8b4plougher if(progress) { 22371b42101056befe25b5f19d5b099e806a2ecee9cdplougher disable_progress_bar(); 22385c7885bc293ab675812fd77a05f59c2917e3e8b4plougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 22391b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_inodes - total_files + total_blocks, columns); 22405c7885bc293ab675812fd77a05f59c2917e3e8b4plougher } 2241eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2242443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2243443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2244443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2245443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2246443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2247443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2248443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2249443c15812032991c98b33b5424b17bcd55fe3575plougher } 2250eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 22519dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2252443c15812032991c98b33b5424b17bcd55fe3575plougher} 2253