unsquashfs.c revision e1542da6a3f99db8dc60b5cad891547e047861b7
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, 6cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * 2012, 2013 783d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher * Phillip Lougher <phillip@squashfs.org.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> 35cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#include <sys/time.h> 36cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#include <sys/resource.h> 372b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher#include <limits.h> 38e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher#include <ctype.h> 39cdebd2b8ae4b1ac39eefb5f0c556f0d2e3dc3d24plougher 408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *fragment_cache, *data_cache; 418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *to_reader, *to_deflate, *to_writer, *from_writer; 428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_t *thread, *deflator_thread; 438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_mutex_t fragment_mutex; 448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* user options that control parallelisation */ 468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint processors = -1; 478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 486490378e5b5e8dc058daf28423a7465699a6ba7bplougherstruct super_block sBlk; 4902bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_operations s_ops; 50efda88fd6fbb19543a86b5f8d15b437bba8c4674plougherstruct compressor *comp; 5102bc3bcabf2b219f63961f07293b83629948f026plougher 529dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, 539dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher dev_count = 0, fifo_count = 0; 54443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 55443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 56443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 57443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 58443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 59443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 60443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 61443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 62443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 63ae271cc93e3684d5314bcdc45b631e497ae43166plougherunsigned int block_log; 64d4204758f77acb5a371fa1487a755b76a05d5476plougherint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; 65d4204758f77acb5a371fa1487a755b76a05d5476plougherint use_regex = FALSE; 66443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 679dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint root_process; 68eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint columns; 69eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint rotate = 0; 701b42101056befe25b5f19d5b099e806a2ecee9cdplougherpthread_mutex_t screen_mutex; 71eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherpthread_cond_t progress_wait; 721b42101056befe25b5f19d5b099e806a2ecee9cdplougherint progress = TRUE, progress_enabled = FALSE; 73eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int total_blocks = 0, total_files = 0, total_inodes = 0; 74eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int cur_blocks = 0; 75ed5124f016834932db2c63d60d259d846171c216plougherint inode_number = 1; 76df9d38a515489c2c573754ad81abd230dfd8b1f0plougherint no_xattrs = XATTR_DEF; 77498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougherint user_xattrs = FALSE; 78443c15812032991c98b33b5424b17bcd55fe3575plougher 79476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 80476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 81476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 82476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 83476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 84476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 85476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 86476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 87476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 88476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 89eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFREG, 90eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFLNK, 91eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFBLK, 92eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFCHR, 93eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFIFO, 94eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFSOCK 95476dcb48b24efff22caa970f000e151f1b28918dplougher}; 96476dcb48b24efff22caa970f000e151f1b28918dplougher 97476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 98476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 99476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 100476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 101476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 102476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 103476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 104476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 105476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 106476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 107476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 108476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 109476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 110476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 111476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 112476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 113476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 114476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 115476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 116476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 117476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 118476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 1198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 1208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar(); 124eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 125afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher#define MAX_LINE 16384 126afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher 127eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 128eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 129eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 130eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 131eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 132c27a3d72b339d80d38623a4ee5a42601338fb4c9plougher if(isatty(STDOUT_FILENO)) 133d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 134d4204758f77acb5a371fa1487a755b76a05d5476plougher "columns\n"); 135eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 136eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 137eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 138eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 139eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1411b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 1421b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 1431b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 1441b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 1451b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1461b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1472b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint add_overflow(int a, int b) 1482b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1492b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX - a) < b; 1502b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1512b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1522b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1532b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint shift_overflow(int a, int shift) 1542b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1552b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX >> shift) < a; 1562b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1572b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1582b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1592b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint multiply_overflow(int a, int multiplier) 1602b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1612b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX / multiplier) < a; 1622b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 1668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 1688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 17062b2d7649ad84234afd928a43f9a2c1612eef361plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1722b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(size, 1) || 1732b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher multiply_overflow(size + 1, sizeof(void *))) 1742b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Size too large in queue_init\n"); 1752b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1767b53be8c83b949517c343d9c6d88243578753c3aplougher queue->data = malloc(sizeof(void *) * (size + 1)); 1777b53be8c83b949517c343d9c6d88243578753c3aplougher if(queue->data == NULL) 1780e0cc6f6dccdc5460c292b0a5accc1184a07f3f5plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 1818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 1828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 1878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1908888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 1918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 1938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 1978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 1988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 2008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 2018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 2028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2068888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 2078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 2098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 2108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 2128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 2138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 2158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 2168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 2178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 2208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2248888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 2258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 2278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 2298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 2308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 2318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 2338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2378888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 2388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 2408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 2418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 242c435240f52b78b0ef498118727ba8dad186db26bplougher cache->hash_table[CALCULATE_HASH(entry->block)] = 243c435240f52b78b0ef498118727ba8dad186db26bplougher entry->hash_next; 2448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 2468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 2488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2528888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 2538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 2558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 2568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 2578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 2588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 2598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 2618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 2628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2678888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 2688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->free_prev == NULL && entry->free_next == NULL) 2708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 2718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 272222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 2738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 2748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 2778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 2788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 2798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 2848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 2888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 2908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 292360570574b8f7786728d91d5fe4a0a4aa291fa03plougher EXIT_UNSQUASH("Out of memory in cache_init\n"); 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 2998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 3008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 3018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 3028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 3108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 311d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 312d4204758f77acb5a371fa1487a755b76a05d5476plougher * Get a block out of the cache. If the block isn't in the cache 313d4204758f77acb5a371fa1487a755b76a05d5476plougher * it is added and queued to the reader() and deflate() threads for 314c435240f52b78b0ef498118727ba8dad186db26bplougher * reading off disk and decompression. The cache grows until max_blocks 315c435240f52b78b0ef498118727ba8dad186db26bplougher * is reached, once this occurs existing discarded blocks on the free 316c435240f52b78b0ef498118727ba8dad186db26bplougher * list are reused 317d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 3228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 3248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 3258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 328d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 3290a0d045642e8e413f90b770539193d3fd1522786plougher * found the block in the cache, increment used count and 3308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * if necessary remove from free list so it won't disappear 3318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 3338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 336d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 337d4204758f77acb5a371fa1487a755b76a05d5476plougher * not in the cache 338d4204758f77acb5a371fa1487a755b76a05d5476plougher * 339d4204758f77acb5a371fa1487a755b76a05d5476plougher * first try to allocate new block 340d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 3438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 3447227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 3467227416360c2f249a0783dffef6725ad03b61c99plougher if(entry->data == NULL) 3477227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 3498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 3518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 352d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 353d4204758f77acb5a371fa1487a755b76a05d5476plougher * try to get from free list 354d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 3568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 357d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&cache->wait_for_free, 358d4204758f77acb5a371fa1487a755b76a05d5476plougher &cache->mutex); 3598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 3618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 3638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 365d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 366d4204758f77acb5a371fa1487a755b76a05d5476plougher * initialise block and insert into the hash table 367d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 3698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 3708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 3718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 3728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 3738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 3748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 375d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 376c435240f52b78b0ef498118727ba8dad186db26bplougher * queue to read thread to read and ultimately (via the 377c435240f52b78b0ef498118727ba8dad186db26bplougher * decompress threads) decompress the buffer 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 3818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 3848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3878888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 3888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 389d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 390d4204758f77acb5a371fa1487a755b76a05d5476plougher * mark cache entry as being complete, reading and (if necessary) 3918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 3928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 393d4204758f77acb5a371fa1487a755b76a05d5476plougher * becomes ready but with an error... 394d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 3988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 399d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 400c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_pending flag is set, one or more threads may be waiting 401c435240f52b78b0ef498118727ba8dad186db26bplougher * on this buffer 402d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 4048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 4058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 4068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4128888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 4138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 414d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 415d4204758f77acb5a371fa1487a755b76a05d5476plougher * wait for this cache entry to become ready, when reading and (if 416d4204758f77acb5a371fa1487a755b76a05d5476plougher * necessary) decompression has taken place 417d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 4218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 422d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&entry->cache->wait_for_pending, 423d4204758f77acb5a371fa1487a755b76a05d5476plougher &entry->cache->mutex); 4248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4308888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 4318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 432d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 433d4204758f77acb5a371fa1487a755b76a05d5476plougher * finished with this cache entry, once the usage count reaches zero it 434c435240f52b78b0ef498118727ba8dad186db26bplougher * can be reused and is put onto the free list. As it remains 435c435240f52b78b0ef498118727ba8dad186db26bplougher * accessible via the hash table it can be found getting a new lease of 436c435240f52b78b0ef498118727ba8dad186db26bplougher * life before it is reused. 437d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 4418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 4428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 4438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 444d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 445c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_free flag is set, one or more threads may be 446c435240f52b78b0ef498118727ba8dad186db26bplougher * waiting on this buffer 447d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 4498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 4508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 4518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 456476dcb48b24efff22caa970f000e151f1b28918dplougher 457476dcb48b24efff22caa970f000e151f1b28918dplougher 458476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 459476dcb48b24efff22caa970f000e151f1b28918dplougher{ 460476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 461476dcb48b24efff22caa970f000e151f1b28918dplougher 462476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 463476dcb48b24efff22caa970f000e151f1b28918dplougher 464476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 465476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 466476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 467476dcb48b24efff22caa970f000e151f1b28918dplougher } 468476dcb48b24efff22caa970f000e151f1b28918dplougher 469476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 470476dcb48b24efff22caa970f000e151f1b28918dplougher} 471476dcb48b24efff22caa970f000e151f1b28918dplougher 472476dcb48b24efff22caa970f000e151f1b28918dplougher 4733edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 4746f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 475476dcb48b24efff22caa970f000e151f1b28918dplougher{ 476afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char str[11], dummy[12], dummy2[12]; /* overflow safe */ 477afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char *userstr, *groupstr; 4786f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 479476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 480476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 48188facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 482476dcb48b24efff22caa970f000e151f1b28918dplougher 483476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 484476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 485476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 486476dcb48b24efff22caa970f000e151f1b28918dplougher } 487476dcb48b24efff22caa970f000e151f1b28918dplougher 488266b83c3b162a6764407753909712fcaade951f2plougher user = getpwuid(inode->uid); 489266b83c3b162a6764407753909712fcaade951f2plougher if(user == NULL) { 490afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy, 12, "%d", inode->uid); 491afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 492afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 493afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 494afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 495afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 496afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = "*"; 497afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 498afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = dummy; 4993edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5003edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 5013edfa57b6a463f7d441d995559143f4861d62e98plougher 502266b83c3b162a6764407753909712fcaade951f2plougher group = getgrgid(inode->gid); 503266b83c3b162a6764407753909712fcaade951f2plougher if(group == NULL) { 504afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy2, 12, "%d", inode->gid); 505afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 506afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 507afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 508afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 509afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 510afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = "*"; 511afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 512afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = dummy2; 5133edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5143edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 5153edfa57b6a463f7d441d995559143f4861d62e98plougher 5166f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 5173edfa57b6a463f7d441d995559143f4861d62e98plougher 5186f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 5193edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 5203edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 5213edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 5223edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 5233edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 524c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 525c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr); 5263edfa57b6a463f7d441d995559143f4861d62e98plougher 527c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%*lld ", padchars > 0 ? padchars : 0, 528c435240f52b78b0ef498118727ba8dad186db26bplougher inode->data); 5293edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5303edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 5313edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 532c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 533c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr) - 7; 5343edfa57b6a463f7d441d995559143f4861d62e98plougher 535d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", 536c435240f52b78b0ef498118727ba8dad186db26bplougher (int) inode->data >> 8, (int) inode->data & 537c435240f52b78b0ef498118727ba8dad186db26bplougher 0xff); 5383edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5393edfa57b6a463f7d441d995559143f4861d62e98plougher } 540476dcb48b24efff22caa970f000e151f1b28918dplougher 5416f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 54288facddfd83e48a907b82210ddccbb4f84d80aecplougher 543d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, 544d4204758f77acb5a371fa1487a755b76a05d5476plougher t->tm_mday, t->tm_hour, t->tm_min, pathname); 5456f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 5466f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 5473edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 5483edfa57b6a463f7d441d995559143f4861d62e98plougher 549476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 550476dcb48b24efff22caa970f000e151f1b28918dplougher} 551476dcb48b24efff22caa970f000e151f1b28918dplougher 552443c15812032991c98b33b5424b17bcd55fe3575plougher 553e3206fad5b70e7e0527db2a627ad26616a8a2429ploughervoid add_entry(struct hash_table_entry *hash_table[], long long start, 554e3206fad5b70e7e0527db2a627ad26616a8a2429plougher int bytes) 555443c15812032991c98b33b5424b17bcd55fe3575plougher{ 556443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 557443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 558443c15812032991c98b33b5424b17bcd55fe3575plougher 559cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher hash_table_entry = malloc(sizeof(struct hash_table_entry)); 560cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher if(hash_table_entry == NULL) 5614a39fa82d4614c18d2977be7898d78d20ba01a49plougher EXIT_UNSQUASH("Out of memory in add_entry\n"); 562443c15812032991c98b33b5424b17bcd55fe3575plougher 563443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 564443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 565443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 566443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 567443c15812032991c98b33b5424b17bcd55fe3575plougher} 568443c15812032991c98b33b5424b17bcd55fe3575plougher 569443c15812032991c98b33b5424b17bcd55fe3575plougher 570f404f4914fdb272a70e18664e8963d793cc90f44plougherint lookup_entry(struct hash_table_entry *hash_table[], long long start) 571443c15812032991c98b33b5424b17bcd55fe3575plougher{ 572443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 573443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 574443c15812032991c98b33b5424b17bcd55fe3575plougher 5759dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 5769dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 5777a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher 578443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 579443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 580443c15812032991c98b33b5424b17bcd55fe3575plougher 581443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 582443c15812032991c98b33b5424b17bcd55fe3575plougher} 583443c15812032991c98b33b5424b17bcd55fe3575plougher 584443c15812032991c98b33b5424b17bcd55fe3575plougher 5853306cb2b54a60a32664617118336ac141e1471b6plougherint read_fs_bytes(int fd, long long byte, int bytes, void *buff) 586443c15812032991c98b33b5424b17bcd55fe3575plougher{ 587443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 588d7f3de3408089ce187d8bc26f6072730c77628daplougher int res, count; 589443c15812032991c98b33b5424b17bcd55fe3575plougher 590c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, 591c435240f52b78b0ef498118727ba8dad186db26bplougher bytes); 592fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 593443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 5945d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 595443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 596443c15812032991c98b33b5424b17bcd55fe3575plougher } 597443c15812032991c98b33b5424b17bcd55fe3575plougher 598d7f3de3408089ce187d8bc26f6072730c77628daplougher for(count = 0; count < bytes; count += res) { 599d7f3de3408089ce187d8bc26f6072730c77628daplougher res = read(fd, buff + count, bytes - count); 600d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res < 1) { 601d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res == 0) { 602e3206fad5b70e7e0527db2a627ad26616a8a2429plougher ERROR("Read on filesystem failed because " 603e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "EOF\n"); 604d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 605d7f3de3408089ce187d8bc26f6072730c77628daplougher } else if(errno != EINTR) { 606d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because %s\n", 607d7f3de3408089ce187d8bc26f6072730c77628daplougher strerror(errno)); 608d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 609d7f3de3408089ce187d8bc26f6072730c77628daplougher } else 610d7f3de3408089ce187d8bc26f6072730c77628daplougher res = 0; 611d7f3de3408089ce187d8bc26f6072730c77628daplougher } 612443c15812032991c98b33b5424b17bcd55fe3575plougher } 613443c15812032991c98b33b5424b17bcd55fe3575plougher 614443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 615443c15812032991c98b33b5424b17bcd55fe3575plougher} 616443c15812032991c98b33b5424b17bcd55fe3575plougher 617443c15812032991c98b33b5424b17bcd55fe3575plougher 618cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougherint read_block(int fd, long long start, long long *next, int expected, 619cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher void *block) 620443c15812032991c98b33b5424b17bcd55fe3575plougher{ 621443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 622cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int offset = 2, res, compressed; 623cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int outlen = expected ? expected : SQUASHFS_METADATA_SIZE; 624443c15812032991c98b33b5424b17bcd55fe3575plougher 625443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 626923b301e304637fd5e587eb05a6f44558abae2bdplougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 627fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 628923b301e304637fd5e587eb05a6f44558abae2bdplougher c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); 629443c15812032991c98b33b5424b17bcd55fe3575plougher } else 6303306cb2b54a60a32664617118336ac141e1471b6plougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 631fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 632fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 633d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, 634d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? 635d4204758f77acb5a371fa1487a755b76a05d5476plougher "compressed" : "uncompressed"); 636443c15812032991c98b33b5424b17bcd55fe3575plougher 63727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) 638443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 639443c15812032991c98b33b5424b17bcd55fe3575plougher 640cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher compressed = SQUASHFS_COMPRESSED(c_byte); 641cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 642cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 643cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher /* 644cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * The block size should not be larger than 645cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * the uncompressed size (or max uncompressed size if 646cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * expected is 0) 647cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher */ 648cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(c_byte > outlen) 649cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return 0; 650cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 651cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(compressed) { 652cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher char buffer[c_byte]; 653cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int error; 654cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 655cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_fs_bytes(fd, start + offset, c_byte, buffer); 656cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(res == FALSE) 657fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 658443c15812032991c98b33b5424b17bcd55fe3575plougher 659b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, buffer, c_byte, 660cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher outlen, &error); 661efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 662efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 663efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 664efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 665fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 666443c15812032991c98b33b5424b17bcd55fe3575plougher } 667443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 668cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_fs_bytes(fd, start + offset, c_byte, block); 669cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(res == FALSE) 670fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 671cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = c_byte; 672443c15812032991c98b33b5424b17bcd55fe3575plougher } 673fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 674cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(next) 675cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher *next = start + offset + c_byte; 676cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 677cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher /* 678cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * if expected, then check the (uncompressed) return data 679cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * is of the expected size 680cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher */ 681cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(expected && expected != res) 682cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return 0; 683cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher else 684cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return res; 685cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 686fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 68768ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher ERROR("read_block: failed to read block @0x%llx\n", start); 688fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 689443c15812032991c98b33b5424b17bcd55fe3575plougher} 690443c15812032991c98b33b5424b17bcd55fe3575plougher 691443c15812032991c98b33b5424b17bcd55fe3575plougher 692443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 693443c15812032991c98b33b5424b17bcd55fe3575plougher{ 694efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 695443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 696443c15812032991c98b33b5424b17bcd55fe3575plougher 697d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, 698c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : 699c435240f52b78b0ef498118727ba8dad186db26bplougher "uncompressed"); 700fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 701443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 70286561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, data) == FALSE) 70368ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 704443c15812032991c98b33b5424b17bcd55fe3575plougher 705b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, data, c_byte, 706b48442b2e37b3cb7efbffb032968f115eec7963cplougher block_size, &error); 707efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 708efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 709efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 710efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 71168ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 712443c15812032991c98b33b5424b17bcd55fe3575plougher } 713443c15812032991c98b33b5424b17bcd55fe3575plougher 714efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 715443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 71686561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, block) == FALSE) 71768ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 718443c15812032991c98b33b5424b17bcd55fe3575plougher 719443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 720443c15812032991c98b33b5424b17bcd55fe3575plougher } 72168ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher 72268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougherfailed: 723d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, 724c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte); 72568ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher return FALSE; 726443c15812032991c98b33b5424b17bcd55fe3575plougher} 727443c15812032991c98b33b5424b17bcd55fe3575plougher 728443c15812032991c98b33b5424b17bcd55fe3575plougher 7291ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougherint read_inode_table(long long start, long long end) 730443c15812032991c98b33b5424b17bcd55fe3575plougher{ 731443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 732443c15812032991c98b33b5424b17bcd55fe3575plougher 7331ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher TRACE("read_inode_table: start %lld, end %lld\n", start, end); 7341ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 735443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 736c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 737c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher inode_table = realloc(inode_table, size += 738c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher SQUASHFS_METADATA_SIZE); 7391ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(inode_table == NULL) { 7401ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("Out of memory in read_inode_table"); 7411ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 7421ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher } 743c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher } 7441ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 745443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 7461ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 747cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_block(fd, start, &start, 0, inode_table + bytes); 748c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) { 7491ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("read_inode_table: failed to read block\n"); 7501ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 751443c15812032991c98b33b5424b17bcd55fe3575plougher } 752443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 753066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 754066439a35c69c023ca15156da81987fe5264475fPhillip Lougher /* 755066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * If this is not the last metadata block in the inode table 756066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * then it should be SQUASHFS_METADATA_SIZE in size. 757066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * Note, we can't use expected in read_block() above for this 758066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * because we don't know if this is the last block until 759066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * after reading. 760066439a35c69c023ca15156da81987fe5264475fPhillip Lougher */ 7611ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(start != end && res != SQUASHFS_METADATA_SIZE) { 7621ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("read_inode_table: metadata block should be %d " 7631ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher "bytes in length, it is %d bytes\n", 7641ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher SQUASHFS_METADATA_SIZE, res); 765066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 7661ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 7671ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher } 768443c15812032991c98b33b5424b17bcd55fe3575plougher } 7691ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 7701ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher return TRUE; 7711ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 7721ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougherfailed: 7731ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher free(inode_table); 7741ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher return FALSE; 775443c15812032991c98b33b5424b17bcd55fe3575plougher} 776443c15812032991c98b33b5424b17bcd55fe3575plougher 777443c15812032991c98b33b5424b17bcd55fe3575plougher 778d4204758f77acb5a371fa1487a755b76a05d5476plougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, 779fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher unsigned int xattr, unsigned int set_mode) 780443c15812032991c98b33b5424b17bcd55fe3575plougher{ 7816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 782443c15812032991c98b33b5424b17bcd55fe3575plougher 7832ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, xattr); 7842ef25cb004cc6995bd36f781863aa844fe8c358dplougher 785443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 786d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to set time on %s, because %s\n", 787d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 788443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 789443c15812032991c98b33b5424b17bcd55fe3575plougher } 790443c15812032991c98b33b5424b17bcd55fe3575plougher 7919dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 7926f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 793c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("set_attributes: failed to change uid and gids " 794c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s, because %s\n", pathname, 795c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 796443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 797443c15812032991c98b33b5424b17bcd55fe3575plougher } 7989dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 7999dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 8009dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 8019dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 802d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change mode %s, because %s\n", 803d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 8049dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 805443c15812032991c98b33b5424b17bcd55fe3575plougher } 806443c15812032991c98b33b5424b17bcd55fe3575plougher 807443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 808443c15812032991c98b33b5424b17bcd55fe3575plougher} 809443c15812032991c98b33b5424b17bcd55fe3575plougher 810443c15812032991c98b33b5424b17bcd55fe3575plougher 8111c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougherint write_bytes(int fd, char *buff, int bytes) 8121c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher{ 8131c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher int res, count; 8141c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8151c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher for(count = 0; count < bytes; count += res) { 8161c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = write(fd, buff + count, bytes - count); 8171c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(res == -1) { 8181c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(errno != EINTR) { 819c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Write on output file failed because " 820c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", strerror(errno)); 8211c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return -1; 8221c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8231c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = 0; 8241c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8251c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8261c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8271c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return 0; 8281c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher} 8291c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8301c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 831b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 832c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherchar *zero_data = NULL; 833b9cee889506e674726856035dba52d5e1cceeb99plougher 83487f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougherint write_block(int file_fd, char *buffer, int size, long long hole, int sparse) 835b9cee889506e674726856035dba52d5e1cceeb99plougher{ 836b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 837b9cee889506e674726856035dba52d5e1cceeb99plougher 838b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 839c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse && lseek_broken == FALSE) { 840c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error = lseek(file_fd, off, SEEK_CUR); 841c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == -1) 842c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher /* failed to seek beyond end of file */ 843c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher lseek_broken = TRUE; 844c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher } 845c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 846c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if((sparse == FALSE || lseek_broken) && zero_data == NULL) { 847b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 848c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("write_block: failed to alloc " 849c435240f52b78b0ef498118727ba8dad186db26bplougher "zero data block\n"); 850b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 851b9cee889506e674726856035dba52d5e1cceeb99plougher } 852c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 853c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse == FALSE || lseek_broken) { 854b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 855b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 856b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 857d4204758f77acb5a371fa1487a755b76a05d5476plougher avail_bytes = hole > block_size ? block_size : 858d4204758f77acb5a371fa1487a755b76a05d5476plougher hole; 859d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_bytes(file_fd, zero_data, avail_bytes) 860d4204758f77acb5a371fa1487a755b76a05d5476plougher == -1) 861b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 862b9cee889506e674726856035dba52d5e1cceeb99plougher } 863b9cee889506e674726856035dba52d5e1cceeb99plougher } 864b9cee889506e674726856035dba52d5e1cceeb99plougher } 865b9cee889506e674726856035dba52d5e1cceeb99plougher 8661c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(write_bytes(file_fd, buffer, size) == -1) 867b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 868b9cee889506e674726856035dba52d5e1cceeb99plougher 869b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 870b9cee889506e674726856035dba52d5e1cceeb99plougher 871b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 872b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 873b9cee889506e674726856035dba52d5e1cceeb99plougher} 874b9cee889506e674726856035dba52d5e1cceeb99plougher 8758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 876cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; 877cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_cond_t open_empty = PTHREAD_COND_INITIALIZER; 878cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_unlimited, open_count; 879cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#define OPEN_FILE_MARGIN 10 880cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 881cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 882cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid open_init(int count) 883cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 884cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count = count; 885cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_unlimited = count == -1; 886cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 887cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 888cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 889cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_wait(char *pathname, int flags, mode_t mode) 890cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 891cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 892cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 893cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher while (open_count == 0) 894cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_wait(&open_empty, &open_mutex); 895cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count --; 896cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 897cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 898cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 899cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher return open(pathname, flags, mode); 900cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 901cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 902cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 903cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid close_wake(int fd) 904cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 905cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close(fd); 906cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 907cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 908cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 909cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count ++; 910cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_signal(&open_empty); 911cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 912cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 913cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 914cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 915cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 9162c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_file(char *pathname, int file_fd, struct inode *inode) 9172c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 9182c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 9192c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 9202c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_file: unable to malloc file\n"); 9212c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9222c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = file_fd; 9232c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->file_size = inode->data; 9242c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = inode->mode; 9252c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = inode->gid; 9262c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = inode->uid; 9272c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = inode->time; 9282c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 9292c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 9302c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->sparse = inode->sparse; 9312c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = inode->xattr; 9322c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 9332c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 9342c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9352c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9362c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_dir(char *pathname, struct dir *dir) 9372c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 9382c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 9392c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 9402c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_dir: unable to malloc file\n"); 9412c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9422c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = -1; 9432c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = dir->mode; 9442c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = dir->guid; 9452c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = dir->uid; 9462c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = dir->mtime; 9472c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 9482c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = dir->xattr; 9492c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 9502c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 9512c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9522c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 95379df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 954443c15812032991c98b33b5424b17bcd55fe3575plougher{ 9558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 956f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 95779df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 95879df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 959443c15812032991c98b33b5424b17bcd55fe3575plougher 96079df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 961443c15812032991c98b33b5424b17bcd55fe3575plougher 962cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher file_fd = open_wait(pathname, O_CREAT | O_WRONLY | 963cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); 964d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file_fd == -1) { 965d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("write_file: failed to create file %s, because %s\n", 966d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 967443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 968443c15812032991c98b33b5424b17bcd55fe3575plougher } 969443c15812032991c98b33b5424b17bcd55fe3575plougher 9706037584bc3e861ff932f5244105959c56c8560e3plougher block_list = malloc(inode->blocks * sizeof(unsigned int)); 9716037584bc3e861ff932f5244105959c56c8560e3plougher if(block_list == NULL) 9728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 973443c15812032991c98b33b5424b17bcd55fe3575plougher 97479df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 975443c15812032991c98b33b5424b17bcd55fe3575plougher 976d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 977d4204758f77acb5a371fa1487a755b76a05d5476plougher * the writer thread is queued a squashfs_file structure describing the 978009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * file. If the file has one or more blocks or a fragment they are 979c435240f52b78b0ef498118727ba8dad186db26bplougher * queued separately (references to blocks in the cache). 980d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 9812c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_file(pathname, file_fd, inode); 982443c15812032991c98b33b5424b17bcd55fe3575plougher 98379df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 9848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 9858372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 9868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 9878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 9888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 9898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 990d4204758f77acb5a371fa1487a755b76a05d5476plougher block->size = i == file_end ? inode->data & (block_size - 1) : 991d4204758f77acb5a371fa1487a755b76a05d5476plougher block_size; 992009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher if(block_list[i] == 0) /* sparse block */ 9938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 9948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 995d4204758f77acb5a371fa1487a755b76a05d5476plougher block->buffer = cache_get(data_cache, start, 996d4204758f77acb5a371fa1487a755b76a05d5476plougher block_list[i]); 9978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 998443c15812032991c98b33b5424b17bcd55fe3575plougher } 9998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1000443c15812032991c98b33b5424b17bcd55fe3575plougher } 1001443c15812032991c98b33b5424b17bcd55fe3575plougher 100279df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 10038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 10048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 10058372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 10068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 10088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 100979df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 10108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 101179df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 101279df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 10138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1014b9cee889506e674726856035dba52d5e1cceeb99plougher } 1015b9cee889506e674726856035dba52d5e1cceeb99plougher 1016b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 1017443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1018443c15812032991c98b33b5424b17bcd55fe3575plougher} 1019476dcb48b24efff22caa970f000e151f1b28918dplougher 1020476dcb48b24efff22caa970f000e151f1b28918dplougher 10216f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 1022443c15812032991c98b33b5424b17bcd55fe3575plougher{ 10236f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 1024443c15812032991c98b33b5424b17bcd55fe3575plougher 10256f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 1026443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 10276013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 10286013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 10296013a30bd39550decc2546a47e5168e57bfcfde8plougher 10306f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 1031c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create hardlink, " 1032c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", strerror(errno)); 1033443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1034443c15812032991c98b33b5424b17bcd55fe3575plougher } 1035443c15812032991c98b33b5424b17bcd55fe3575plougher 1036443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1037443c15812032991c98b33b5424b17bcd55fe3575plougher } 1038443c15812032991c98b33b5424b17bcd55fe3575plougher 10396f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 10406f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 10416f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 1042c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("create_inode: regular file, file_size %lld, " 1043c435240f52b78b0ef498118727ba8dad186db26bplougher "blocks %d\n", i->data, i->blocks); 1044443c15812032991c98b33b5424b17bcd55fe3575plougher 104579df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 1046443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 1047443c15812032991c98b33b5424b17bcd55fe3575plougher break; 10486f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 104999ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSYMLINK_TYPE: 1050d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: symlink, symlink_size %lld\n", 1051d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data); 1052443c15812032991c98b33b5424b17bcd55fe3575plougher 1053a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1054a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1055a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 10566f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 1057c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create symlink " 1058c435240f52b78b0ef498118727ba8dad186db26bplougher "%s, because %s\n", pathname, 1059c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1060443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1061443c15812032991c98b33b5424b17bcd55fe3575plougher } 1062443c15812032991c98b33b5424b17bcd55fe3575plougher 10632ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, i->xattr); 10642ef25cb004cc6995bd36f781863aa844fe8c358dplougher 10659dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 10666f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 1067c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to change " 1068c435240f52b78b0ef498118727ba8dad186db26bplougher "uid and gids on %s, because " 1069c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", pathname, 1070c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1071443c15812032991c98b33b5424b17bcd55fe3575plougher } 1072443c15812032991c98b33b5424b17bcd55fe3575plougher 1073443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 1074443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1075443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 107699ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_CHRDEV_TYPE: 107799ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LBLKDEV_TYPE: 107899ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LCHRDEV_TYPE: { 10796f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 1080545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 1081443c15812032991c98b33b5424b17bcd55fe3575plougher 10829dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 1083a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1084a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1085a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 10866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 1087d4204758f77acb5a371fa1487a755b76a05d5476plougher makedev((i->data >> 8) & 0xff, 1088d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data & 0xff)) == -1) { 1089c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create " 1090c435240f52b78b0ef498118727ba8dad186db26bplougher "%s device %s, because %s\n", 1091d4204758f77acb5a371fa1487a755b76a05d5476plougher chrdev ? "character" : "block", 1092d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 1093443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1094443c15812032991c98b33b5424b17bcd55fe3575plougher } 1095c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, 1096fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->gid, i->time, i->xattr, TRUE); 1097443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 1098443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1099c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: could not create %s " 1100c435240f52b78b0ef498118727ba8dad186db26bplougher "device %s, because you're not " 1101c435240f52b78b0ef498118727ba8dad186db26bplougher "superuser!\n", chrdev ? "character" : 1102c435240f52b78b0ef498118727ba8dad186db26bplougher "block", pathname); 1103443c15812032991c98b33b5424b17bcd55fe3575plougher break; 11046f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1105443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 110699ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LFIFO_TYPE: 1107443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 1108443c15812032991c98b33b5424b17bcd55fe3575plougher 1109a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1110a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1111a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 1112443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 1113d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create fifo %s, " 1114d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, 1115d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 1116443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1117443c15812032991c98b33b5424b17bcd55fe3575plougher } 1118c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, i->gid, 1119fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->time, i->xattr, TRUE); 1120443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 1121443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1122443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 112399ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSOCKET_TYPE: 1124443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 1125443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 1126443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1127443c15812032991c98b33b5424b17bcd55fe3575plougher default: 1128d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Unknown inode type %d in create_inode_table!\n", 1129d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type); 1130443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1131443c15812032991c98b33b5424b17bcd55fe3575plougher } 1132fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 11336f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 1134443c15812032991c98b33b5424b17bcd55fe3575plougher 1135443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1136443c15812032991c98b33b5424b17bcd55fe3575plougher} 1137443c15812032991c98b33b5424b17bcd55fe3575plougher 1138443c15812032991c98b33b5424b17bcd55fe3575plougher 1139e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougherint read_directory_table(long long start, long long end) 1140443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1141443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 1142443c15812032991c98b33b5424b17bcd55fe3575plougher 1143e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher TRACE("read_directory_table: start %lld, end %lld\n", start, end); 114441da3230b2ac91a73f9190676f66b3d80b21c270plougher 1145443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 114607d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 114707d4d0dcafeb198a568f859b88034637e6e7a8e7plougher directory_table = realloc(directory_table, size += 114807d4d0dcafeb198a568f859b88034637e6e7a8e7plougher SQUASHFS_METADATA_SIZE); 1149e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(directory_table == NULL) { 1150e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher ERROR("Out of memory in " 1151e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher "read_directory_table\n"); 1152e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1153e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 115407d4d0dcafeb198a568f859b88034637e6e7a8e7plougher } 1155e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1156443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 1157e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1158cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_block(fd, start, &start, 0, directory_table + bytes); 1159e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(res == 0) { 1160e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher ERROR("read_directory_table: failed to read block\n"); 1161e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1162e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 1163e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1164443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 1165066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 1166066439a35c69c023ca15156da81987fe5264475fPhillip Lougher /* 1167066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * If this is not the last metadata block in the directory table 1168066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * then it should be SQUASHFS_METADATA_SIZE in size. 1169066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * Note, we can't use expected in read_block() above for this 1170066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * because we don't know if this is the last block until 1171066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * after reading. 1172066439a35c69c023ca15156da81987fe5264475fPhillip Lougher */ 1173e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(start != end && res != SQUASHFS_METADATA_SIZE) { 1174e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher ERROR("uncompress_directory_table: metadata block " 1175e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher "should be %d bytes in length, it is %d " 1176066439a35c69c023ca15156da81987fe5264475fPhillip Lougher "bytes\n", SQUASHFS_METADATA_SIZE, res); 1177e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1178e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 1179443c15812032991c98b33b5424b17bcd55fe3575plougher } 1180e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1181e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher return TRUE; 1182e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1183e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougherfailed: 1184e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher free(directory_table); 1185e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher return FALSE; 1186443c15812032991c98b33b5424b17bcd55fe3575plougher} 1187443c15812032991c98b33b5424b17bcd55fe3575plougher 1188443c15812032991c98b33b5424b17bcd55fe3575plougher 11899dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 11909dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1191443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1192443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1193443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1194443c15812032991c98b33b5424b17bcd55fe3575plougher 1195443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1196443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1197443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1198443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1199443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1200443c15812032991c98b33b5424b17bcd55fe3575plougher 1201443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1202443c15812032991c98b33b5424b17bcd55fe3575plougher} 1203443c15812032991c98b33b5424b17bcd55fe3575plougher 1204443c15812032991c98b33b5424b17bcd55fe3575plougher 1205443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1206443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1207443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1208443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1209443c15812032991c98b33b5424b17bcd55fe3575plougher} 1210443c15812032991c98b33b5424b17bcd55fe3575plougher 1211443c15812032991c98b33b5424b17bcd55fe3575plougher 121204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougherchar *get_component(char *target, char **targname) 1213b54566f5c433764830c29c83151691d0034de094plougher{ 121404281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *start; 121504281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 1216b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 12173cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1218b54566f5c433764830c29c83151691d0034de094plougher 121904281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher start = target; 1220b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 122104281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target ++; 1222b54566f5c433764830c29c83151691d0034de094plougher 122304281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher *targname = strndup(start, target - start); 1224b54566f5c433764830c29c83151691d0034de094plougher 1225b54566f5c433764830c29c83151691d0034de094plougher return target; 1226b54566f5c433764830c29c83151691d0034de094plougher} 1227b54566f5c433764830c29c83151691d0034de094plougher 1228b54566f5c433764830c29c83151691d0034de094plougher 12296ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 12306ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 12316ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 12326ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12336ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 12346ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 12356ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 12366ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 12376ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 12386ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 12396ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 12406ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 12416ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 12426ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12436ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 12446ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 12456ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12466ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12474dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1248b54566f5c433764830c29c83151691d0034de094plougher{ 124904281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *targname; 12504dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 125171add234b27054974d5e29f95b3fab3072792a62plougher 1252b7bb000643cd21c615a0366a7365441aa9c433f2plougher TRACE("add_path: adding \"%s\" extract file\n", target); 1253b7bb000643cd21c615a0366a7365441aa9c433f2plougher 125404281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target = get_component(target, &targname); 125571add234b27054974d5e29f95b3fab3072792a62plougher 125671add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 12579dd4507fac1c96098eda8abe699a813a59451633plougher paths = malloc(sizeof(struct pathname)); 12589dd4507fac1c96098eda8abe699a813a59451633plougher if(paths == NULL) 12594dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 12604dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 126171add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 126271add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 126371add234b27054974d5e29f95b3fab3072792a62plougher } 126471add234b27054974d5e29f95b3fab3072792a62plougher 126571add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 126671add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 126771add234b27054974d5e29f95b3fab3072792a62plougher break; 126871add234b27054974d5e29f95b3fab3072792a62plougher 12696ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 1270d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1271d4204758f77acb5a371fa1487a755b76a05d5476plougher * allocate new name entry 1272d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 127371add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 1274d4204758f77acb5a371fa1487a755b76a05d5476plougher paths->name = realloc(paths->name, (i + 1) * 1275d4204758f77acb5a371fa1487a755b76a05d5476plougher sizeof(struct path_entry)); 1276fd628227871aecb36bb2b4f9c7f664f731510cdeplougher if(paths->name == NULL) 1277fd628227871aecb36bb2b4f9c7f664f731510cdeplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 127804281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher paths->name[i].name = targname; 12796ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 12804dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 12814dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 12821f3cc42a2f77966d321a38d1709eba26f71104bdplougher if(paths->name[i].preg == NULL) 12831f3cc42a2f77966d321a38d1709eba26f71104bdplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 1284d4204758f77acb5a371fa1487a755b76a05d5476plougher error = regcomp(paths->name[i].preg, targname, 1285d4204758f77acb5a371fa1487a755b76a05d5476plougher REG_EXTENDED|REG_NOSUB); 1286545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 128762859d215e7f828ace8501f5863f0c3d8b48ebf3Phillip Lougher char str[1024]; /* overflow safe */ 12884dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 12894dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 1290d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("invalid regex %s in export %s, " 1291c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", targname, alltarget, 1292c435240f52b78b0ef498118727ba8dad186db26bplougher str); 12934dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 12944dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 12954dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 12966ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12976ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 1298d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1299d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component 1300d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 130171add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 130271add234b27054974d5e29f95b3fab3072792a62plougher else 1303d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1304d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1305d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13064dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 13076ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 1308d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1309d4204758f77acb5a371fa1487a755b76a05d5476plougher * existing matching entry 1310d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 131104281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher free(targname); 131204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 13136ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 1314d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1315c435240f52b78b0ef498118727ba8dad186db26bplougher * No sub-directory which means this is the leaf 1316c435240f52b78b0ef498118727ba8dad186db26bplougher * component of a pre-existing extract which subsumes 1317c435240f52b78b0ef498118727ba8dad186db26bplougher * the extract currently being added, in which case stop 1318c435240f52b78b0ef498118727ba8dad186db26bplougher * adding components 1319d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13206ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 1321d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1322d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component and child components exist 1323c435240f52b78b0ef498118727ba8dad186db26bplougher * from more specific extracts, delete as they're 1324c435240f52b78b0ef498118727ba8dad186db26bplougher * subsumed by this extract 1325d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13266ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 13276ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 13286ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 1329d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1330d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1331d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13326ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 133371add234b27054974d5e29f95b3fab3072792a62plougher } 133471add234b27054974d5e29f95b3fab3072792a62plougher 133571add234b27054974d5e29f95b3fab3072792a62plougher return paths; 133671add234b27054974d5e29f95b3fab3072792a62plougher} 13376ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 13386ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1339a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 134071add234b27054974d5e29f95b3fab3072792a62plougher{ 13418372232d2460411adaa2299c32a0a88665e44902plougher struct pathnames *new = malloc(sizeof(struct pathnames)); 1342c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher if(new == NULL) 1343c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher EXIT_UNSQUASH("Out of memory in init_subdir\n"); 1344a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1345a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1346a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1347a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1348a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1349a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1350a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 13513488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths->count % PATHS_ALLOC_SIZE == 0) { 1352d4204758f77acb5a371fa1487a755b76a05d5476plougher paths = realloc(paths, sizeof(struct pathnames *) + 13533488d3bb3b89c394534ad2be909b661771a9581bplougher (paths->count + PATHS_ALLOC_SIZE) * 13543488d3bb3b89c394534ad2be909b661771a9581bplougher sizeof(struct pathname *)); 13553488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths == NULL) 13563488d3bb3b89c394534ad2be909b661771a9581bplougher EXIT_UNSQUASH("Out of memory in add_subdir\n"); 13573488d3bb3b89c394534ad2be909b661771a9581bplougher } 1358a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1359a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1360a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1361a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1362a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1363a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1364a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1365a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1366a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1367a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1368a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1369a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1370a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1371a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1372a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 137371add234b27054974d5e29f95b3fab3072792a62plougher 137471add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 137571add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1376b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 137771add234b27054974d5e29f95b3fab3072792a62plougher } 137871add234b27054974d5e29f95b3fab3072792a62plougher 1379a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1380a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1381a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1382a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1383a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1384a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1385c435240f52b78b0ef498118727ba8dad186db26bplougher regexec(path->name[i].preg, name, (size_t) 0, 1386c435240f52b78b0ef498118727ba8dad186db26bplougher NULL, 0) == 0 : fnmatch(path->name[i].name, 1387c435240f52b78b0ef498118727ba8dad186db26bplougher name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 1388c435240f52b78b0ef498118727ba8dad186db26bplougher 0; 1389a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1390d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1391d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a leaf component, any subdirectories 1392c435240f52b78b0ef498118727ba8dad186db26bplougher * will implicitly match, therefore return an 1393c435240f52b78b0ef498118727ba8dad186db26bplougher * empty new search set 1394d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1395a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1396a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1397a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1398d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1399d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a non-leaf component, add any 1400c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to the new set of 1401c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to scan for this name 1402d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1403a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1404a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1405a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1406b54566f5c433764830c29c83151691d0034de094plougher 1407a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1408d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1409d4204758f77acb5a371fa1487a755b76a05d5476plougher * no matching names found, delete empty search set, and return 1410d4204758f77acb5a371fa1487a755b76a05d5476plougher * FALSE 1411d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1412a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1413a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1414a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1415a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1416a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1417d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 14180a0d045642e8e413f90b770539193d3fd1522786plougher * one or more matches with sub-directories found (no leaf matches), 14190a0d045642e8e413f90b770539193d3fd1522786plougher * return new search set and return TRUE 14200a0d045642e8e413f90b770539193d3fd1522786plougher */ 1421a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1422a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1423a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 1424d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1425d4204758f77acb5a371fa1487a755b76a05d5476plougher * found matching leaf exclude, return empty search set and return TRUE 1426d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1427a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1428a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1429a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1430b54566f5c433764830c29c83151691d0034de094plougher} 1431b54566f5c433764830c29c83151691d0034de094plougher 1432b54566f5c433764830c29c83151691d0034de094plougher 1433b807ab3497c01a49fed6f9daafce3bfc599a9421ploughervoid pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1434d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1435eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1436eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 1437454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *name; 1438eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 1439eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1440eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1441eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1442cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) 1443cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1444cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1445eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1446eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1447454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *pathname; 1448454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher int res; 1449eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1450d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", 1451d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1452eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1453eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 1454eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1455eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1456454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1457454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher if(res == -1) 1458454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1459eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1460eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 1461eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 1462eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 1463d4204758f77acb5a371fa1487a755b76a05d5476plougher if(type == SQUASHFS_FILE_TYPE || 1464d4204758f77acb5a371fa1487a755b76a05d5476plougher type == SQUASHFS_LREG_TYPE) { 1465312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 1466eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 1467d4204758f77acb5a371fa1487a755b76a05d5476plougher created_inode[i->inode_number - 1] = 1468d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) i; 1469d4204758f77acb5a371fa1487a755b76a05d5476plougher total_blocks += (i->data + 1470d4204758f77acb5a371fa1487a755b76a05d5476plougher (block_size - 1)) >> block_log; 1471eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1472eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 1473eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1474eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 1475eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1476eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1477eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 1478454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher free(pathname); 1479eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1480eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1481eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 1482eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1483eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1484eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1485a2cff53655359b044ea88baa76cb16d1c8f44d2aploughervoid dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1486d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1487443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1488443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1489d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *name; 1490a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 1491eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1492eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1493443c15812032991c98b33b5424b17bcd55fe3575plougher 1494cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) { 1495cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher ERROR("dir_scan: failed to read directory %s, skipping\n", 1496cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher parent_name); 1497cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1498cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher } 1499cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1500eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 1501eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 1502eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 15032c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!lsonly) { 15042c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15052c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Make directory with default User rwx permissions rather than 15062c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * the permissions from the filesystem, as these may not have 15072c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * write/execute permission. These are fixed up later in 15082c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * set_attributes(). 15092c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15102c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher int res = mkdir(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 15112c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(res == -1) { 15122c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15132c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Skip directory if mkdir fails, unless we're 15142c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * forcing and the error is -EEXIST 15152c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15162c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!force || errno != EEXIST) { 15172c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to make directory %s, " 15182c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "because %s\n", parent_name, 15192c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher strerror(errno)); 15202c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher squashfs_closedir(dir); 15212c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher return; 15222c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 15232c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 15242c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15252c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Try to change permissions of existing directory so 15262c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * that we can write to it 15272c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15282c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher res = chmod(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 15292c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if (res == -1) 15302c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to change permissions " 15312c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "for directory %s, because %s\n", 15322c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher parent_name, strerror(errno)); 15332c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 153485917a285edbd4bb78f1b245f66c634d1e0d4029plougher } 1535443c15812032991c98b33b5424b17bcd55fe3575plougher 1536443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1537d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *pathname; 1538d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher int res; 1539d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher 1540d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", 1541d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1542b54566f5c433764830c29c83151691d0034de094plougher 154371add234b27054974d5e29f95b3fab3072792a62plougher 154471add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 1545b54566f5c433764830c29c83151691d0034de094plougher continue; 1546b54566f5c433764830c29c83151691d0034de094plougher 1547d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1548d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher if(res == -1) 1549d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1550fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1551443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 155271add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 1553a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher else if(new == NULL) { 1554312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 15556f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 15566f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 15576f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 15586f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1559eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!lsonly) { 15606f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 1561eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher update_progress_bar(); 1562eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1563427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher 1564d4204758f77acb5a371fa1487a755b76a05d5476plougher if(i->type == SQUASHFS_SYMLINK_TYPE || 1565d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type == SQUASHFS_LSYMLINK_TYPE) 1566427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher free(i->symlink); 15676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1568a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1569a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 1570d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher free(pathname); 1571443c15812032991c98b33b5424b17bcd55fe3575plougher } 1572443c15812032991c98b33b5424b17bcd55fe3575plougher 1573074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 15742c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_dir(parent_name, dir); 1575443c15812032991c98b33b5424b17bcd55fe3575plougher 1576443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 1577443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 1578443c15812032991c98b33b5424b17bcd55fe3575plougher} 1579443c15812032991c98b33b5424b17bcd55fe3575plougher 1580443c15812032991c98b33b5424b17bcd55fe3575plougher 1581b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 1582b624936abba03d38b7e9245c647339d8f6f34274plougher{ 158327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher time_t mkfs_time = (time_t) sBlk.s.mkfs_time; 1584b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 1585b624936abba03d38b7e9245c647339d8f6f34274plougher 1586b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 1587d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 158827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "little endian " : 158927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1590b624936abba03d38b7e9245c647339d8f6f34274plougher#else 1591d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 159227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "big endian " : 159327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1594b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 1595c766500607f1ea7494b8360409be3d8ea66f9761plougher 1596d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : 1597d4204758f77acb5a371fa1487a755b76a05d5476plougher "failed to get time\n"); 1598e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", 1599e3206fad5b70e7e0527db2a627ad26616a8a2429plougher sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / 1600e3206fad5b70e7e0527db2a627ad26616a8a2429plougher (1024.0 * 1024.0)); 1601c766500607f1ea7494b8360409be3d8ea66f9761plougher 160227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 1603e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Compression %s\n", comp->name); 1604c766500607f1ea7494b8360409be3d8ea66f9761plougher 160527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Block size %d\n", sBlk.s.block_size); 1606d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem is %sexportable via NFS\n", 160727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); 1608d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Inodes are %scompressed\n", 160927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); 1610d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Data is %scompressed\n", 161127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); 1612c766500607f1ea7494b8360409be3d8ea66f9761plougher 16137ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(sBlk.s.s_major > 1) { 16147ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) 16157ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are not stored\n"); 16167ca09d1320cdc30a068f179b93ca5c141b55c395plougher else { 16177ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are %scompressed\n", 16187ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? 16197ca09d1320cdc30a068f179b93ca5c141b55c395plougher "un" : ""); 16207ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Always_use_fragments option is %sspecified\n", 16217ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : 16227ca09d1320cdc30a068f179b93ca5c141b55c395plougher "not "); 16237ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 16247ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 16257ca09d1320cdc30a068f179b93ca5c141b55c395plougher 1626de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(sBlk.s.s_major == 4) { 1627de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) 1628de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are not stored\n"); 1629de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher else 1630de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are %scompressed\n", 1631de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? 1632de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher "un" : ""); 1633de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher } 1634de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher 1635ba95dd35ef0e9f618d926ddc1a595076adc23818plougher if(sBlk.s.s_major < 4) 1636ba95dd35ef0e9f618d926ddc1a595076adc23818plougher printf("Check data is %spresent in the filesystem\n", 1637ba95dd35ef0e9f618d926ddc1a595076adc23818plougher SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : 1638ba95dd35ef0e9f618d926ddc1a595076adc23818plougher "not "); 1639c766500607f1ea7494b8360409be3d8ea66f9761plougher 164027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 1641d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Duplicates are %sremoved\n", 164227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); 16430337de3977eec74e6a3d28e0d0863299246de8b7plougher else 16440337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 1645c766500607f1ea7494b8360409be3d8ea66f9761plougher 164627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 164727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of fragments %d\n", sBlk.s.fragments); 1648c766500607f1ea7494b8360409be3d8ea66f9761plougher 164927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of inodes %d\n", sBlk.s.inodes); 1650c766500607f1ea7494b8360409be3d8ea66f9761plougher 165127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 165227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of ids %d\n", sBlk.s.no_ids); 16530f74340e3b68533339adc60f418ddf59fa188f61plougher else { 16540f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of uids %d\n", sBlk.no_uids); 16550f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of gids %d\n", sBlk.no_guids); 16560f74340e3b68533339adc60f418ddf59fa188f61plougher } 1657b624936abba03d38b7e9245c647339d8f6f34274plougher 165827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); 165927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.directory_table_start 0x%llx\n", 166027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 1661c766500607f1ea7494b8360409be3d8ea66f9761plougher 16620ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 1) 16630ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", 16640ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.fragment_table_start); 16650ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 16660ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 2) 16670ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.lookup_table_start 0x%llx\n\n", 16680ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.lookup_table_start); 16690ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 1670053da34003852e494400c1ade35b526e1821b576plougher if(sBlk.s.s_major == 4) { 167127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); 1672053da34003852e494400c1ade35b526e1821b576plougher TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", 1673053da34003852e494400c1ade35b526e1821b576plougher sBlk.s.xattr_id_table_start); 1674053da34003852e494400c1ade35b526e1821b576plougher } else { 16750f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 16760f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); 16770f74340e3b68533339adc60f418ddf59fa188f61plougher } 1678b624936abba03d38b7e9245c647339d8f6f34274plougher} 1679b624936abba03d38b7e9245c647339d8f6f34274plougher 1680b624936abba03d38b7e9245c647339d8f6f34274plougher 168102bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 1682443c15812032991c98b33b5424b17bcd55fe3575plougher{ 16836490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block_3 sBlk_3; 168464e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher struct squashfs_super_block sBlk_4; 16856490378e5b5e8dc058daf28423a7465699a6ba7bplougher 16866490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 16876490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Try to read a Squashfs 4 superblock 16886490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 168964e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), 16903306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_4); 169154660e177ba40ab08ee2f3304b9f030eb5675677plougher swap = sBlk_4.s_magic != SQUASHFS_MAGIC; 16926490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); 16936490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1694d4204758f77acb5a371fa1487a755b76a05d5476plougher if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && 1695d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk_4.s_minor == 0) { 16966490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.squashfs_opendir = squashfs_opendir_4; 16976490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment = read_fragment_4; 16986490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment_table = read_fragment_table_4; 16996490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_block_list = read_block_list_2; 17006490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_inode = read_inode_4; 17016490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_uids_guids = read_uids_guids_4; 17026490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); 1703efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1704efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 1705efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher * Check the compression type 1706efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 170727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher comp = lookup_compressor_id(sBlk.s.compression); 17086490378e5b5e8dc058daf28423a7465699a6ba7bplougher return TRUE; 17096490378e5b5e8dc058daf28423a7465699a6ba7bplougher } 17106490378e5b5e8dc058daf28423a7465699a6ba7bplougher 17116490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 17126490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock 17136490378e5b5e8dc058daf28423a7465699a6ba7bplougher * (compatible with 1 and 2 filesystems) 17146490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 171586561909d9ca51a4e4ce4efcfea30b41d1d08275plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), 17163306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_3); 1717443c15812032991c98b33b5424b17bcd55fe3575plougher 1718d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1719d4204758f77acb5a371fa1487a755b76a05d5476plougher * Check it is a SQUASHFS superblock 1720d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1721443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 172221ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic != SQUASHFS_MAGIC) { 172321ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { 17247a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher squashfs_super_block_3 sblk; 1725c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Reading a different endian SQUASHFS filesystem " 1726c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s\n", source); 17276490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); 17286490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); 1729443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 1730443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 1731c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Can't find a SQUASHFS superblock on %s\n", 1732c435240f52b78b0ef498118727ba8dad186db26bplougher source); 1733443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1734443c15812032991c98b33b5424b17bcd55fe3575plougher } 1735443c15812032991c98b33b5424b17bcd55fe3575plougher } 1736443c15812032991c98b33b5424b17bcd55fe3575plougher 173727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_magic = sBlk_3.s_magic; 173827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inodes = sBlk_3.inodes; 173927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.mkfs_time = sBlk_3.mkfs_time; 174027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size; 174127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragments = sBlk_3.fragments; 174227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_log = sBlk_3.block_log; 174327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.flags = sBlk_3.flags; 174427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major = sBlk_3.s_major; 174527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor = sBlk_3.s_minor; 174627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.root_inode = sBlk_3.root_inode; 174727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used; 174827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start; 174927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start; 175027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; 175127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; 17526490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_uids = sBlk_3.no_uids; 17536490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_guids = sBlk_3.no_guids; 17546490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start; 17556490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start; 175627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 17576490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1758443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 175927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { 176027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used_2; 17616490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start_2; 17626490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start_2; 176327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; 176427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; 176502bc3bcabf2b219f63961f07293b83629948f026plougher 176627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1) { 176727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size_1; 176827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk.uid_start; 1769ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1770ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 1771ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 17726f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 177379e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1774ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 177527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = 1776c435240f52b78b0ef498118727ba8dad186db26bplougher sBlk_3.fragment_table_start_2; 1777ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1778ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 1779ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 1780ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 17816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 178279e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1783ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 178427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher } else if(sBlk.s.s_major == 3) { 1785ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_3; 1786ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment = read_fragment_3; 1787ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment_table = read_fragment_table_3; 1788ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 1789ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_inode = read_inode_3; 179079e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 179102bc3bcabf2b219f63961f07293b83629948f026plougher } else { 179227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, 179327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor); 17944c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 1795443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1796443c15812032991c98b33b5424b17bcd55fe3575plougher } 1797443c15812032991c98b33b5424b17bcd55fe3575plougher 1798efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 179999c8abf4de4297b3159355a0cefe9ad6f5182827plougher * 1.x, 2.x and 3.x filesystems use gzip compression. 1800efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 1801efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp = lookup_compressor("gzip"); 1802443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1803443c15812032991c98b33b5424b17bcd55fe3575plougher 1804443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 1805443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1806443c15812032991c98b33b5424b17bcd55fe3575plougher} 1807443c15812032991c98b33b5424b17bcd55fe3575plougher 1808443c15812032991c98b33b5424b17bcd55fe3575plougher 1809a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 181071add234b27054974d5e29f95b3fab3072792a62plougher{ 181171add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 1812afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher char buffer[MAX_LINE + 1]; /* overflow safe */ 1813e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher char *name; 181471add234b27054974d5e29f95b3fab3072792a62plougher 181563e21ee4b795bb900f82c18e7b5c6f7369907360plougher fd = fopen(filename, "r"); 181663e21ee4b795bb900f82c18e7b5c6f7369907360plougher if(fd == NULL) 1817e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Failed to open extract file \"%s\" because %s\n", 1818e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 1819e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1820afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher while(fgets(name = buffer, MAX_LINE + 1, fd) != NULL) { 1821e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher int len = strlen(name); 1822e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1823afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher if(len == MAX_LINE && name[len - 1] != '\n') 1824e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* line too large */ 1825e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Line too long when reading " 1826afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher "extract file \"%s\", larger than %d " 182783847c1beb852a7b3f5906a0f4c90be659e46794Phillip Lougher "bytes\n", filename, MAX_LINE); 1828e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1829e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* 1830e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * Remove '\n' terminator if it exists (the last line 1831e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * in the file may not be '\n' terminated) 1832e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1833e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(len && name[len - 1] == '\n') 1834e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name[len - 1] = '\0'; 1835e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1836e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* Skip any leading whitespace */ 1837e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher while(isspace(*name)) 1838e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1839e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1840e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if comment line, skip */ 1841e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '#') 1842e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 1843e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1844e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* check for initial backslash, to accommodate 1845e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * filenames with leading space or leading # character 1846e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1847e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\\') 1848e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1849e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1850e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if line is now empty after skipping characters, skip it */ 1851e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\0') 1852e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 185371add234b27054974d5e29f95b3fab3072792a62plougher 1854a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 1855e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher } 1856e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1857e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(ferror(fd)) 1858e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Reading extract file \"%s\" failed because %s\n", 1859e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 186071add234b27054974d5e29f95b3fab3072792a62plougher 186171add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 1862a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 186371add234b27054974d5e29f95b3fab3072792a62plougher} 186471add234b27054974d5e29f95b3fab3072792a62plougher 186571add234b27054974d5e29f95b3fab3072792a62plougher 1866d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1867d4204758f77acb5a371fa1487a755b76a05d5476plougher * reader thread. This thread processes read requests queued by the 1868d4204758f77acb5a371fa1487a755b76a05d5476plougher * cache_get() routine. 1869d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18708888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 18718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 18728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 18738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 187486561909d9ca51a4e4ce4efcfea30b41d1d08275plougher int res = read_fs_bytes(fd, entry->block, 18758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 18768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 18778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 1879d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1880c435240f52b78b0ef498118727ba8dad186db26bplougher * queue successfully read block to the deflate 1881c435240f52b78b0ef498118727ba8dad186db26bplougher * thread(s) for further processing 1882d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_deflate, entry); 18848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1885d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1886d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has either been successfully read and is 1887d4204758f77acb5a371fa1487a755b76a05d5476plougher * uncompressed, or an error has occurred, clear pending 1888c435240f52b78b0ef498118727ba8dad186db26bplougher * flag, set error appropriately, and wake up any 1889c435240f52b78b0ef498118727ba8dad186db26bplougher * threads waiting on this buffer 1890d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 18928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 18948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1896d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1897d4204758f77acb5a371fa1487a755b76a05d5476plougher * writer thread. This processes file write requests queued by the 1898d4204758f77acb5a371fa1487a755b76a05d5476plougher * write_file() routine. 1899d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 19008888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 19018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 19028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 19038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 19058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 19068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 190787f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougher long long hole = 0; 190827636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 1909c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error; 19108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 19128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 19138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 19142c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } else if(file->fd == -1) { 19152c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* write attributes for directory file->pathname */ 19162c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher set_attributes(file->pathname, file->mode, file->uid, 19172c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid, file->time, file->xattr, TRUE); 19182c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file->pathname); 19192c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file); 19202c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher continue; 19218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 19248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 19268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1927eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 19288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 19298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 19318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 19328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 19338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 19348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 193727636cb2cec37a68313f9eb825c0548245eecad0plougher 193827636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 193927636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 194027636cb2cec37a68313f9eb825c0548245eecad0plougher 1941c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(failed) 1942c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher continue; 1943c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1944c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher error = write_block(file_fd, block->buffer->data + 1945c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher block->offset, block->size, hole, file->sparse); 1946c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1947c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == FALSE) { 1948d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write data block %d\n", 1949d4204758f77acb5a371fa1487a755b76a05d5476plougher i); 195027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 19518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 1952c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 19538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 19548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 19558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 19568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 195827636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 1959d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1960d4204758f77acb5a371fa1487a755b76a05d5476plougher * corner case for hole extending to end of file 1961d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1962d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file->sparse == FALSE || 1963d4204758f77acb5a371fa1487a755b76a05d5476plougher lseek(file_fd, hole, SEEK_CUR) == -1) { 1964d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1965d4204758f77acb5a371fa1487a755b76a05d5476plougher * for files which we don't want to write 1966c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * sparsely, or for broken lseeks which cannot 1967c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * seek beyond end of file, write_block will do 1968c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * the right thing 1969c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher */ 19708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 1971d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_block(file_fd, "\0", 1, hole, 1972d4204758f77acb5a371fa1487a755b76a05d5476plougher file->sparse) == FALSE) { 1973d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse " 1974d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 197527636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 19768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 1978d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse data " 1979d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 198027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 19818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1984cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close_wake(file_fd); 198527636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 1986d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(file->pathname, file->mode, file->uid, 1987fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher file->gid, file->time, file->xattr, force); 198827636cb2cec37a68313f9eb825c0548245eecad0plougher else { 198927636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 199027636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 199127636cb2cec37a68313f9eb825c0548245eecad0plougher } 199279df93becb68081effabebba3006c794be308598plougher free(file->pathname); 19938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 199427636cb2cec37a68313f9eb825c0548245eecad0plougher 19958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 19978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1999d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 2000d4204758f77acb5a371fa1487a755b76a05d5476plougher * decompress thread. This decompresses buffers queued by the read thread 2001d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 20028888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *deflator(void *arg) 20038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 20048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 20058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 20078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_deflate); 2008efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 2009efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 2010b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, tmp, entry->data, 2011efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, 2012efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher &error); 2013efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 2014efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) 2015efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 2016efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 2017efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher else 2018efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher memcpy(entry->data, tmp, res); 20198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2020d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 2021d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has been either successfully decompressed, or an error 20228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 2023d4204758f77acb5a371fa1487a755b76a05d5476plougher * wake up any threads waiting on this block 2024d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 2025efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher cache_block_ready(entry, res == -1); 20268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 20288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2030eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 2031eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2032eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timeval timeval; 2033eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timespec timespec; 20341b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 20351b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 20361b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 20371b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 203801b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher if(isatty(STDOUT_FILENO)) 203901b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 204001b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher "columns\n"); 20411b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 20421b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 20431b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 20441b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 20451b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 20461b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 20471b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 20481b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 20491b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 20501b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 20511b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 2052eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2053eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_init(&progress_wait, NULL); 2054eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 20551b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2056eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 2057eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher gettimeofday(&timeval, NULL); 2058eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec = timeval.tv_sec; 2059eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(timeval.tv_usec + 250000 > 999999) 2060eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec++; 2061c435240f52b78b0ef498118727ba8dad186db26bplougher timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 2062c435240f52b78b0ef498118727ba8dad186db26bplougher 1000; 2063c435240f52b78b0ef498118727ba8dad186db26bplougher pthread_cond_timedwait(&progress_wait, &screen_mutex, 2064c435240f52b78b0ef498118727ba8dad186db26bplougher ×pec); 20651b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress_enabled) 20661b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 2067d4204758f77acb5a371fa1487a755b76a05d5476plougher fifo_count + cur_blocks, total_inodes - 2068d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks, columns); 2069eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2070eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2071eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2072eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 20738888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 20748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2075cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher struct rlimit rlim; 2076cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher int i, max_files, res; 20778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 20788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 20808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGINT); 20818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 20828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 2083c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 2084c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 20858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 20878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 20888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 20898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 20908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 20928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 20938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 20948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 20958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 20968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 20978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 2099d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Failed to get number of available processors. " 2100d4204758f77acb5a371fa1487a755b76a05d5476plougher "Defaulting to 1\n"); 21018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 21028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 21038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 21049cc26b77a61fefdeb45f5c487c2bfdefd394b66fplougher processors = sysconf(_SC_NPROCESSORS_ONLN); 21058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 21068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 21078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 210870f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher if(add_overflow(processors, 3) || 210970f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher multiply_overflow(processors + 3, sizeof(pthread_t))) 211070f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher EXIT_UNSQUASH("Processors too large\n"); 211170f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher 21126697cff2155192a3e0c182a3cef046ebf215ac32plougher thread = malloc((3 + processors) * sizeof(pthread_t)); 21136697cff2155192a3e0c182a3cef046ebf215ac32plougher if(thread == NULL) 21148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 2115eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher deflator_thread = &thread[3]; 21168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2117cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2118cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * dimensioning the to_reader and to_deflate queues. The size of 2119cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * these queues is directly related to the amount of block 2120cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * read-ahead possible. To_reader queues block read requests to 2121cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the reader thread and to_deflate queues block decompression 2122cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * requests to the deflate thread(s) (once the block has been read by 2123cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the reader thread). The amount of read-ahead is determined by 2124cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the combined size of the data_block and fragment caches which 2125cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * determine the total number of blocks which can be "in flight" 2126cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * at any one time (either being read or being decompressed) 2127cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2128cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * The maximum file open limit, however, affects the read-ahead 2129cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * possible, in that for normal sizes of the fragment and data block 2130cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches, where the incoming files have few data blocks or one fragment 2131cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * only, the file open limit is likely to be reached before the 2132cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches are full. This means the worst case sizing of the combined 2133cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * sizes of the caches is unlikely to ever be necessary. However, is is 2134cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * obvious read-ahead up to the data block cache size is always possible 2135cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * irrespective of the file open limit, because a single file could 2136cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * contain that number of blocks. 2137cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2138cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "file open limit + data block cache size" seems 2139cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * to be a reasonable estimate. We can reasonably assume the maximum 2140cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * likely read-ahead possible is data block cache size + one fragment 2141cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * per open file. 2142cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2143cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * dimensioning the to_writer queue. The size of this queue is 2144cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * directly related to the amount of block read-ahead possible. 2145cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * However, unlike the to_reader and to_deflate queues, this is 2146cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * complicated by the fact the to_writer queue not only contains 2147cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * entries for fragments and data_blocks but it also contains 2148cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * file entries, one per open file in the read-ahead. 2149cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2150cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "2 * (file open limit) + 2151cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * data block cache size" seems to be a reasonable estimate. 2152cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * We can reasonably assume the maximum likely read-ahead possible 2153cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * is data block cache size + one fragment per open file, and then 2154cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * we will have a file_entry for each open file. 2155cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2156cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher res = getrlimit(RLIMIT_NOFILE, &rlim); 2157cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (res == -1) { 2158cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher ERROR("failed to get open file limit! Defaulting to 1\n"); 2159cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher rlim.rlim_cur = 1; 2160cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2161cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2162cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur != RLIM_INFINITY) { 2163cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2164cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * leave OPEN_FILE_MARGIN free (rlim_cur includes fds used by 2165cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * stdin, stdout, stderr and filesystem fd 2166cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2167cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur <= OPEN_FILE_MARGIN) 2168cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* no margin, use minimum possible */ 2169cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = 1; 2170cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher else 2171cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = rlim.rlim_cur - OPEN_FILE_MARGIN; 2172cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else 2173cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = -1; 2174cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2175cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* set amount of available files for use by open_wait and close_wake */ 2176cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_init(max_files); 2177cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2178cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2179cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * allocate to_reader, to_deflate and to_writer queues. Set based on 2180cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * open file limit and cache size, unless open file limit is unlimited, 2181cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * in which case set purely based on cache limits 21822b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 21832b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not overflow 21842b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * a signed int 2185cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2186cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (max_files != -1) { 21872b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(data_buffer_size, max_files) || 21882b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher add_overflow(data_buffer_size, max_files * 2)) 21892b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 21902b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2191cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(max_files + data_buffer_size); 2192cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_deflate = queue_init(max_files + data_buffer_size); 2193cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(max_files * 2 + data_buffer_size); 2194cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else { 21952b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher int all_buffers_size; 21962b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 21972b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(fragment_buffer_size, data_buffer_size)) 21982b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 21992b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 22002b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22012b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher all_buffers_size = fragment_buffer_size + data_buffer_size; 22022b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22032b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(all_buffers_size, all_buffers_size)) 22042b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 22052b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 2206cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2207cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(all_buffers_size); 2208cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_deflate = queue_init(all_buffers_size); 2209cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(all_buffers_size * 2); 2210cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2211cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 22128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 2213cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 22148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 22158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 22168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 22178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 2218eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 22198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 22208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 2222c435240f52b78b0ef498118727ba8dad186db26bplougher if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 2223c435240f52b78b0ef498118727ba8dad186db26bplougher 0) 22248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 22258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 22288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 22298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) 2231c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 2232c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 22338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 22348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22361b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 22371b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 22381b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 22391b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = TRUE; 22401b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 22411b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 22421b42101056befe25b5f19d5b099e806a2ecee9cdplougher 22431b42101056befe25b5f19d5b099e806a2ecee9cdplougher 22441b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 22451b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 22461b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 22471b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 22481b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 22491b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 22501b42101056befe25b5f19d5b099e806a2ecee9cdplougher 22511b42101056befe25b5f19d5b099e806a2ecee9cdplougher 2252eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar() 2253eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 22541b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2255eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_signal(&progress_wait); 22561b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 2257eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2258eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2259eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2260eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 2261eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2262eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 2263b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher int max_digits, used, hashes, spaces; 2264dce832998340bea4236fddb5ba1525121044ce18plougher static int tty = -1; 2265eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2266b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher if(max == 0) 2267b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher return; 2268b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2269b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher max_digits = floor(log10(max)) + 1; 2270b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher used = max_digits * 2 + 11; 2271b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher hashes = (current * (columns - used)) / max; 2272b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher spaces = columns - used - hashes; 2273b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2274eaf639366792995c36ae7295bddf534f6f416643plougher if((current > max) || (columns - used < 0)) 2275eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 2276eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2277dce832998340bea4236fddb5ba1525121044ce18plougher if(tty == -1) 2278dce832998340bea4236fddb5ba1525121044ce18plougher tty = isatty(STDOUT_FILENO); 2279dce832998340bea4236fddb5ba1525121044ce18plougher if(!tty) { 2280dce832998340bea4236fddb5ba1525121044ce18plougher static long long previous = -1; 2281dce832998340bea4236fddb5ba1525121044ce18plougher 22820a0d045642e8e413f90b770539193d3fd1522786plougher /* 22830a0d045642e8e413f90b770539193d3fd1522786plougher * Updating much more frequently than this results in huge 22840a0d045642e8e413f90b770539193d3fd1522786plougher * log files. 22850a0d045642e8e413f90b770539193d3fd1522786plougher */ 2286dce832998340bea4236fddb5ba1525121044ce18plougher if((current % 100) != 0 && current != max) 2287dce832998340bea4236fddb5ba1525121044ce18plougher return; 2288dce832998340bea4236fddb5ba1525121044ce18plougher /* Don't update just to rotate the spinner. */ 2289dce832998340bea4236fddb5ba1525121044ce18plougher if(current == previous) 2290dce832998340bea4236fddb5ba1525121044ce18plougher return; 2291dce832998340bea4236fddb5ba1525121044ce18plougher previous = current; 2292dce832998340bea4236fddb5ba1525121044ce18plougher } 2293dce832998340bea4236fddb5ba1525121044ce18plougher 2294eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 2295eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2296eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 2297eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 2298eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2299eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 2300eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2301eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 2302eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 2303eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2304eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 2305eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 2306eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 2307eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2308eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2309eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 23102b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint parse_number(char *arg, int *res) 23112b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 23122b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher char *b; 23132b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher long number = strtol(arg, &b, 10); 23142b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23152b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check for trailing junk after number */ 23162b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(*b != '\0') 23172b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 23182b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23197f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher /* 23207f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * check for strtol underflow or overflow in conversion. 23217f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * Note: strtol can validly return LONG_MIN and LONG_MAX 23227f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * if the user entered these values, but, additional code 23237f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * to distinguish this scenario is unnecessary, because for 23247f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * our purposes LONG_MIN and LONG_MAX are too large anyway 23257f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher */ 23262b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number == LONG_MIN || number == LONG_MAX) 23272b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 23282b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23292b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* reject negative numbers as invalid */ 23302b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number < 0) 23312b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 23322b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23332b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check if long result will overflow signed int */ 23342b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number > INT_MAX) 23352b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 23362b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23372b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher *res = number; 23382b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 1; 23392b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 23402b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23412b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2342443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 2343e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher printf("unsquashfs version 4.2-git (2013/01/31)\n");\ 2344e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher printf("copyright (C) 2013 Phillip Lougher "\ 234583d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher "<phillip@squashfs.org.uk>\n\n");\ 2346e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is free software; you can redistribute it and/or"\ 2347d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2348e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("modify it under the terms of the GNU General Public License"\ 2349d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2350e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("as published by the Free Software Foundation; either version "\ 2351e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "2,\n");\ 2352e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("or (at your option) any later version.\n\n");\ 2353e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is distributed in the hope that it will be "\ 2354e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "useful,\n");\ 2355d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ 2356d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2357d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ 2358d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2359443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 2360443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 2361443c15812032991c98b33b5424b17bcd55fe3575plougher{ 2362443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 2363b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 2364545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 2365a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 2366a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 2367e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher long long directory_table_end; 2368ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 2369ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 2370443c15812032991c98b33b5424b17bcd55fe3575plougher 23711b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 2372545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 2373545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 23749dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 23759dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 2376443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 2377443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 2378443c15812032991c98b33b5424b17bcd55fe3575plougher break; 2379d4204758f77acb5a371fa1487a755b76a05d5476plougher if(strcmp(argv[i], "-version") == 0 || 2380d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-v") == 0) { 2381443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 2382443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 2383d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-info") == 0 || 2384d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-i") == 0) 2385443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 2386c435240f52b78b0ef498118727ba8dad186db26bplougher else if(strcmp(argv[i], "-ls") == 0 || 2387c435240f52b78b0ef498118727ba8dad186db26bplougher strcmp(argv[i], "-l") == 0) 2388443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 2389d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-no-progress") == 0 || 2390d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-n") == 0) 2391296d7d8a68e33341d68f4354b5e1fe2f3aa275a6plougher progress = FALSE; 239231638061a6de0cb89093672aa71ddeb42f2eb28aplougher else if(strcmp(argv[i], "-no-xattrs") == 0 || 239331638061a6de0cb89093672aa71ddeb42f2eb28aplougher strcmp(argv[i], "-no") == 0) 239431638061a6de0cb89093672aa71ddeb42f2eb28aplougher no_xattrs = TRUE; 2395df9d38a515489c2c573754ad81abd230dfd8b1f0plougher else if(strcmp(argv[i], "-xattrs") == 0 || 2396df9d38a515489c2c573754ad81abd230dfd8b1f0plougher strcmp(argv[i], "-x") == 0) 2397df9d38a515489c2c573754ad81abd230dfd8b1f0plougher no_xattrs = FALSE; 2398498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher else if(strcmp(argv[i], "-user-xattrs") == 0 || 2399498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher strcmp(argv[i], "-u") == 0) { 2400498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher user_xattrs = TRUE; 2401498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher no_xattrs = FALSE; 2402498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher } else if(strcmp(argv[i], "-dest") == 0 || 2403d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-d") == 0) { 240471add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2405d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -dest missing filename\n", 2406d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 240771add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 240871add234b27054974d5e29f95b3fab3072792a62plougher } 2409443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 2410d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-processors") == 0 || 2411d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-p") == 0) { 2412c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 24132c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher !parse_number(argv[i], 24142c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher &processors)) { 2415d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors missing or invalid " 2416d4204758f77acb5a371fa1487a755b76a05d5476plougher "processor number\n", argv[0]); 24170cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 24180cf5c297bec42c7c220d2825f12f9499f2293279plougher } 24190cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 2420d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors should be 1 or larger\n", 2421d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 24220cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 24230cf5c297bec42c7c220d2825f12f9499f2293279plougher } 2424d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-data-queue") == 0 || 2425d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-da") == 0) { 2426c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 24272b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 24282b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &data_buffer_size)) { 2429c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -data-queue missing or invalid " 2430c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2431ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2432ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2433ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 2434d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue should be 1 Mbyte or " 2435d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2436ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2437ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2438d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || 2439d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-fr") == 0) { 2440c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 24412b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 24422b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &fragment_buffer_size)) { 2443c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -frag-queue missing or invalid " 2444c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2445ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2446ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2447ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 2448d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue should be 1 Mbyte or " 2449d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2450ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2451ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2452d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-force") == 0 || 2453d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-f") == 0) 2454a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 2455d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-stat") == 0 || 2456d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-s") == 0) 2457b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 2458d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-lls") == 0 || 2459d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-ll") == 0) { 24609baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 24619baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2462d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-linfo") == 0 || 2463d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-li") == 0) { 24649baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 24659baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2466d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-ef") == 0 || 2467d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-e") == 0) { 246871add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2469d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -ef missing filename\n", 2470d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 247171add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 247271add234b27054974d5e29f95b3fab3072792a62plougher } 2473a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 2474d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-regex") == 0 || 2475d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-r") == 0) 24764dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 24774dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2478b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2479443c15812032991c98b33b5424b17bcd55fe3575plougher } 2480443c15812032991c98b33b5424b17bcd55fe3575plougher 2481feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher if(lsonly || info) 2482feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher progress = FALSE; 2483feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher 2484bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#ifdef SQUASHFS_TRACE 2485bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher progress = FALSE; 2486bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#endif 2487bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher 2488443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2489443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2490443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 2491d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("SYNTAX: %s [options] filesystem [directories or " 2492d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract]\n", argv[0]); 2493d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-v[ersion]\t\tprint version, licence and " 2494d4204758f77acb5a371fa1487a755b76a05d5476plougher "copyright information\n"); 2495d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " 2496d4204758f77acb5a371fa1487a755b76a05d5476plougher "default \"squashfs-root\"\n"); 2497c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-n[o-progress]\t\tdon't display the progress " 2498c435240f52b78b0ef498118727ba8dad186db26bplougher "bar\n"); 2499df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" 2500df9d38a515489c2c573754ad81abd230dfd8b1f0plougher NOXOPT_STR"\n"); 2501df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-x[attrs]\t\textract xattrs in file system" 2502df9d38a515489c2c573754ad81abd230dfd8b1f0plougher XOPT_STR "\n"); 2503498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher ERROR("\t-u[ser-xattrs]\t\tonly extract user xattrs in " 2504498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher "file system.\n\t\t\t\tEnables extracting " 2505498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher "xattrs\n"); 2506c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-p[rocessors] <number>\tuse <number> " 2507c435240f52b78b0ef498118727ba8dad186db26bplougher "processors. By default will use\n"); 2508c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tnumber of processors available\n"); 2509c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-i[nfo]\t\t\tprint files as they are " 2510c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed\n"); 2511c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-li[nfo]\t\tprint files as they are " 2512c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed with file\n"); 2513c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tattributes (like ls -l output)\n"); 2514d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" 2515d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2516c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-ll[s]\t\t\tlist filesystem with file " 2517c435240f52b78b0ef498118727ba8dad186db26bplougher "attributes (like\n"); 2518c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tls -l output), but don't unsquash\n"); 2519c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-f[orce]\t\tif file already exists then " 2520c435240f52b78b0ef498118727ba8dad186db26bplougher "overwrite\n"); 2521d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " 2522d4204758f77acb5a371fa1487a755b76a05d5476plougher "information\n"); 2523d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-e[f] <extract file>\tlist of directories or " 2524d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract.\n\t\t\t\tOne per line\n"); 2525c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-da[ta-queue] <size>\tSet data queue to " 2526c435240f52b78b0ef498118727ba8dad186db26bplougher "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", 2527d4204758f77acb5a371fa1487a755b76a05d5476plougher DATA_BUFFER_DEFAULT); 25288bc376ba1f7110fb88989e5134b74aa8412fb00eplougher ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " 2529d56f6723626a391b473c2c023b628abcd8ed31e3Phillip Lougher "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", 2530d4204758f77acb5a371fa1487a755b76a05d5476plougher FRAGMENT_BUFFER_DEFAULT); 2531c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX " 2532c435240f52b78b0ef498118727ba8dad186db26bplougher "regular expressions\n"); 2533c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\trather than use the default shell " 2534c435240f52b78b0ef498118727ba8dad186db26bplougher "wildcard\n\t\t\t\texpansion (globbing)\n"); 2535076b053e2cce5c9172b4f385e866c2e606712a32plougher ERROR("\nDecompressors available:\n"); 2536076b053e2cce5c9172b4f385e866c2e606712a32plougher display_compressors("", ""); 2537443c15812032991c98b33b5424b17bcd55fe3575plougher } 2538443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2539443c15812032991c98b33b5424b17bcd55fe3575plougher } 2540443c15812032991c98b33b5424b17bcd55fe3575plougher 254171add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2542a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2543b54566f5c433764830c29c83151691d0034de094plougher 2544443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2545d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Could not open %s, because %s\n", argv[i], 2546d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 2547443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2548443c15812032991c98b33b5424b17bcd55fe3575plougher } 2549443c15812032991c98b33b5424b17bcd55fe3575plougher 255002bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2551443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2552443c15812032991c98b33b5424b17bcd55fe3575plougher 2553b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2554b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2555b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2556b624936abba03d38b7e9245c647339d8f6f34274plougher } 2557b624936abba03d38b7e9245c647339d8f6f34274plougher 2558f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher if(!comp->supported) { 2559f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Filesystem uses %s compression, this is " 2560f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher "unsupported by this version\n", comp->name); 2561f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Decompressors available:\n"); 2562f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher display_compressors("", ""); 2563f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher exit(1); 2564f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher } 2565f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher 256627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_size = sBlk.s.block_size; 256727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_log = sBlk.s.block_log; 2568ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2569009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher /* 25702b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Sanity check block size and block log. 25712b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 25722b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check they're within correct limits 25732b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 25742b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size > SQUASHFS_FILE_MAX_SIZE || 25752b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher block_log > SQUASHFS_FILE_MAX_LOG) 25762b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size or block_log too large." 25772b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 25782b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25792b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 25802b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check block_size and block_log match 25812b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 25822b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size != (1 << block_log)) 25832b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size and block_log do not match." 25842b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 25852b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25862b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 2587009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * convert from queue size in Mbytes to queue size in 25882b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * blocks. 25892b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 25902b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not 25912b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * overflow a signed int 2592009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher */ 25932b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(fragment_buffer_size, 20 - block_log)) 25942b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Fragment queue size is too large\n"); 25952b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 25962b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher fragment_buffer_size <<= 20 - block_log; 25972b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25982b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(data_buffer_size, 20 - block_log)) 25992b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 26002b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 26012b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher data_buffer_size <<= 20 - block_log; 26022b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 26038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 26048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 260544a6967088416c9bd6ee7165bde59c9ba5ccb704plougher fragment_data = malloc(block_size); 260644a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(fragment_data == NULL) 2607443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2608443c15812032991c98b33b5424b17bcd55fe3575plougher 260944a6967088416c9bd6ee7165bde59c9ba5ccb704plougher file_data = malloc(block_size); 261044a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(file_data == NULL) 2611443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2612443c15812032991c98b33b5424b17bcd55fe3575plougher 261344a6967088416c9bd6ee7165bde59c9ba5ccb704plougher data = malloc(block_size); 261444a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(data == NULL) 2615eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2616443c15812032991c98b33b5424b17bcd55fe3575plougher 261744a6967088416c9bd6ee7165bde59c9ba5ccb704plougher created_inode = malloc(sBlk.s.inodes * sizeof(char *)); 261844a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(created_inode == NULL) 2619443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2620443c15812032991c98b33b5424b17bcd55fe3575plougher 262127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 2622443c15812032991c98b33b5424b17bcd55fe3575plougher 26231a7e7e871169a6cb6e3470a50b33db83830886e2plougher if(s_ops.read_uids_guids() == FALSE) 26241a7e7e871169a6cb6e3470a50b33db83830886e2plougher EXIT_UNSQUASH("failed to uid/gid table\n"); 2625ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2626e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher if(s_ops.read_fragment_table(&directory_table_end) == FALSE) 2627cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher EXIT_UNSQUASH("failed to read fragment table\n"); 2628ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 26291ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(read_inode_table(sBlk.s.inode_table_start, 26301ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher sBlk.s.directory_table_start) == FALSE) 26311ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher EXIT_UNSQUASH("failed to read inode table\n"); 2632ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2633e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(read_directory_table(sBlk.s.directory_table_start, 2634e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher directory_table_end) == FALSE) 2635e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher EXIT_UNSQUASH("failed to read directory table\n"); 2636443c15812032991c98b33b5424b17bcd55fe3575plougher 263731638061a6de0cb89093672aa71ddeb42f2eb28aplougher if(no_xattrs) 263831638061a6de0cb89093672aa71ddeb42f2eb28aplougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 263931638061a6de0cb89093672aa71ddeb42f2eb28aplougher 26408935dc25479321709c74c2f8214cf5365669100eplougher if(read_xattrs_from_disk(fd, &sBlk.s) == 0) 26418935dc25479321709c74c2f8214cf5365669100eplougher EXIT_UNSQUASH("failed to read the xattr table\n"); 26428935dc25479321709c74c2f8214cf5365669100eplougher 2643a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2644a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2645a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2646a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2647a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 264827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 264927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2650eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 265127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 26529b58176e667b67770569c9076a410b27aaa3bcf5plougher inode_number = 1; 2653eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2654c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%d inodes (%d blocks) to write\n\n", total_inodes, 2655c435240f52b78b0ef498118727ba8dad186db26bplougher total_inodes - total_files + total_blocks); 2656eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 26571b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 26581b42101056befe25b5f19d5b099e806a2ecee9cdplougher enable_progress_bar(); 26591b42101056befe25b5f19d5b099e806a2ecee9cdplougher 266027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 266127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2662443c15812032991c98b33b5424b17bcd55fe3575plougher 26638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 26648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 26658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 26665c7885bc293ab675812fd77a05f59c2917e3e8b4plougher if(progress) { 26671b42101056befe25b5f19d5b099e806a2ecee9cdplougher disable_progress_bar(); 26685c7885bc293ab675812fd77a05f59c2917e3e8b4plougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 26691b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_inodes - total_files + total_blocks, columns); 26705c7885bc293ab675812fd77a05f59c2917e3e8b4plougher } 2671eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2672443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2673443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2674443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2675443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2676443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2677443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2678443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2679443c15812032991c98b33b5424b17bcd55fe3575plougher } 2680eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 26819dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2682443c15812032991c98b33b5424b17bcd55fe3575plougher} 2683