unsquashfs.c revision afbbfbf11bc846056666d073c94a9c8e84fcb1ca
12f60990fb0352f7a30e0281a066458dbf033618bplougher/* 2e3206fad5b70e7e0527db2a627ad26616a8a2429plougher * Unsquash a squashfs filesystem. This is a highly compressed read only 3e3206fad5b70e7e0527db2a627ad26616a8a2429plougher * filesystem. 4443c15812032991c98b33b5424b17bcd55fe3575plougher * 50ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 60ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher * 2012 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; 77443c15812032991c98b33b5424b17bcd55fe3575plougher 78476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 79476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 80476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 81476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 82476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 83476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 84476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 85476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 86476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 87476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 88eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFREG, 89eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFLNK, 90eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFBLK, 91eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFCHR, 92eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFIFO, 93eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFSOCK 94476dcb48b24efff22caa970f000e151f1b28918dplougher}; 95476dcb48b24efff22caa970f000e151f1b28918dplougher 96476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 97476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 98476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 99476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 100476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 101476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 102476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 103476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 104476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 105476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 106476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 107476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 108476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 109476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 110476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 111476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 112476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 113476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 114476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 115476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 116476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 117476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 1188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 1198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 121eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar(); 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 124afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher#define MAX_LINE 16384 125afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher 126eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 127eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 128eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 129eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 130eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 131c27a3d72b339d80d38623a4ee5a42601338fb4c9plougher if(isatty(STDOUT_FILENO)) 132d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 133d4204758f77acb5a371fa1487a755b76a05d5476plougher "columns\n"); 134eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 135eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 136eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 137eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 138eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1401b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 1411b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 1421b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 1431b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 1441b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1451b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1462b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint add_overflow(int a, int b) 1472b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1482b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX - a) < b; 1492b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1502b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1512b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1522b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint shift_overflow(int a, int shift) 1532b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1542b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX >> shift) < a; 1552b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1562b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1572b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1582b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint multiply_overflow(int a, int multiplier) 1592b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1602b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX / multiplier) < a; 1612b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1622b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 1658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 1678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 16962b2d7649ad84234afd928a43f9a2c1612eef361plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1712b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(size, 1) || 1722b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher multiply_overflow(size + 1, sizeof(void *))) 1732b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Size too large in queue_init\n"); 1742b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1757b53be8c83b949517c343d9c6d88243578753c3aplougher queue->data = malloc(sizeof(void *) * (size + 1)); 1767b53be8c83b949517c343d9c6d88243578753c3aplougher if(queue->data == NULL) 1770e0cc6f6dccdc5460c292b0a5accc1184a07f3f5plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 1808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 1818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 1828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 1868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1898888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 1908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 1928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 1968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 1978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 1998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 2008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 2018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2058888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 2068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 2088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 2098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 2118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 2128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 2148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 2158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 2168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 2198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2238888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 2248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 2268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 2288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 2298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 2308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 2328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2368888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 2378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 2398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 2408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 241c435240f52b78b0ef498118727ba8dad186db26bplougher cache->hash_table[CALCULATE_HASH(entry->block)] = 242c435240f52b78b0ef498118727ba8dad186db26bplougher entry->hash_next; 2438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 2458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 2478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 2528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 2548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 2558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 2568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 2578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 2588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 2608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 2618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 2678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->free_prev == NULL && entry->free_next == NULL) 2698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 2708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 271222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 2728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 2738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 2768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 2778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 2788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 2798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 2838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 2878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 291360570574b8f7786728d91d5fe4a0a4aa291fa03plougher EXIT_UNSQUASH("Out of memory in cache_init\n"); 2928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 2988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 2998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 3008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 3018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 3028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 3098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 310d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 311d4204758f77acb5a371fa1487a755b76a05d5476plougher * Get a block out of the cache. If the block isn't in the cache 312d4204758f77acb5a371fa1487a755b76a05d5476plougher * it is added and queued to the reader() and deflate() threads for 313c435240f52b78b0ef498118727ba8dad186db26bplougher * reading off disk and decompression. The cache grows until max_blocks 314c435240f52b78b0ef498118727ba8dad186db26bplougher * is reached, once this occurs existing discarded blocks on the free 315c435240f52b78b0ef498118727ba8dad186db26bplougher * list are reused 316d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 3188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 3218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 3238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 3248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 3258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 327d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 3280a0d045642e8e413f90b770539193d3fd1522786plougher * found the block in the cache, increment used count and 3298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * if necessary remove from free list so it won't disappear 3308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 3328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 335d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 336d4204758f77acb5a371fa1487a755b76a05d5476plougher * not in the cache 337d4204758f77acb5a371fa1487a755b76a05d5476plougher * 338d4204758f77acb5a371fa1487a755b76a05d5476plougher * first try to allocate new block 339d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 3437227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 3457227416360c2f249a0783dffef6725ad03b61c99plougher if(entry->data == NULL) 3467227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 3488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 3508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 351d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 352d4204758f77acb5a371fa1487a755b76a05d5476plougher * try to get from free list 353d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 3558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 356d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&cache->wait_for_free, 357d4204758f77acb5a371fa1487a755b76a05d5476plougher &cache->mutex); 3588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 3608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 3628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 364d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 365d4204758f77acb5a371fa1487a755b76a05d5476plougher * initialise block and insert into the hash table 366d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 3688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 3698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 3708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 3718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 3728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 3738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 374d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 375c435240f52b78b0ef498118727ba8dad186db26bplougher * queue to read thread to read and ultimately (via the 376c435240f52b78b0ef498118727ba8dad186db26bplougher * decompress threads) decompress the buffer 3778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 3808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 3838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3868888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 3878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 388d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 389d4204758f77acb5a371fa1487a755b76a05d5476plougher * mark cache entry as being complete, reading and (if necessary) 3908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 3918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 392d4204758f77acb5a371fa1487a755b76a05d5476plougher * becomes ready but with an error... 393d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 398d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 399c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_pending flag is set, one or more threads may be waiting 400c435240f52b78b0ef498118727ba8dad186db26bplougher * on this buffer 401d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 4038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 4048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 4058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 4128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 413d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 414d4204758f77acb5a371fa1487a755b76a05d5476plougher * wait for this cache entry to become ready, when reading and (if 415d4204758f77acb5a371fa1487a755b76a05d5476plougher * necessary) decompression has taken place 416d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 421d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&entry->cache->wait_for_pending, 422d4204758f77acb5a371fa1487a755b76a05d5476plougher &entry->cache->mutex); 4238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4298888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 4308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 431d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 432d4204758f77acb5a371fa1487a755b76a05d5476plougher * finished with this cache entry, once the usage count reaches zero it 433c435240f52b78b0ef498118727ba8dad186db26bplougher * can be reused and is put onto the free list. As it remains 434c435240f52b78b0ef498118727ba8dad186db26bplougher * accessible via the hash table it can be found getting a new lease of 435c435240f52b78b0ef498118727ba8dad186db26bplougher * life before it is reused. 436d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 4408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 4418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 4428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 443d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 444c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_free flag is set, one or more threads may be 445c435240f52b78b0ef498118727ba8dad186db26bplougher * waiting on this buffer 446d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 4488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 4498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 4508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 455476dcb48b24efff22caa970f000e151f1b28918dplougher 456476dcb48b24efff22caa970f000e151f1b28918dplougher 457476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 458476dcb48b24efff22caa970f000e151f1b28918dplougher{ 459476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 460476dcb48b24efff22caa970f000e151f1b28918dplougher 461476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 462476dcb48b24efff22caa970f000e151f1b28918dplougher 463476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 464476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 465476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 466476dcb48b24efff22caa970f000e151f1b28918dplougher } 467476dcb48b24efff22caa970f000e151f1b28918dplougher 468476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 469476dcb48b24efff22caa970f000e151f1b28918dplougher} 470476dcb48b24efff22caa970f000e151f1b28918dplougher 471476dcb48b24efff22caa970f000e151f1b28918dplougher 4723edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 4736f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 474476dcb48b24efff22caa970f000e151f1b28918dplougher{ 475afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char str[11], dummy[12], dummy2[12]; /* overflow safe */ 476afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char *userstr, *groupstr; 4776f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 478476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 479476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 48088facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 481476dcb48b24efff22caa970f000e151f1b28918dplougher 482476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 483476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 484476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 485476dcb48b24efff22caa970f000e151f1b28918dplougher } 486476dcb48b24efff22caa970f000e151f1b28918dplougher 487266b83c3b162a6764407753909712fcaade951f2plougher user = getpwuid(inode->uid); 488266b83c3b162a6764407753909712fcaade951f2plougher if(user == NULL) { 489afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy, 12, "%d", inode->uid); 490afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 491afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 492afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 493afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 494afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 495afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = "*"; 496afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 497afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = dummy; 4983edfa57b6a463f7d441d995559143f4861d62e98plougher } else 4993edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 5003edfa57b6a463f7d441d995559143f4861d62e98plougher 501266b83c3b162a6764407753909712fcaade951f2plougher group = getgrgid(inode->gid); 502266b83c3b162a6764407753909712fcaade951f2plougher if(group == NULL) { 503afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy2, 12, "%d", inode->gid); 504afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 505afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 506afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 507afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 508afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 509afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = "*"; 510afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 511afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = dummy2; 5123edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5133edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 5143edfa57b6a463f7d441d995559143f4861d62e98plougher 5156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 5163edfa57b6a463f7d441d995559143f4861d62e98plougher 5176f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 5183edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 5193edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 5203edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 5213edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 5223edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 523c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 524c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr); 5253edfa57b6a463f7d441d995559143f4861d62e98plougher 526c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%*lld ", padchars > 0 ? padchars : 0, 527c435240f52b78b0ef498118727ba8dad186db26bplougher inode->data); 5283edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5293edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 5303edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 531c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 532c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr) - 7; 5333edfa57b6a463f7d441d995559143f4861d62e98plougher 534d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", 535c435240f52b78b0ef498118727ba8dad186db26bplougher (int) inode->data >> 8, (int) inode->data & 536c435240f52b78b0ef498118727ba8dad186db26bplougher 0xff); 5373edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5383edfa57b6a463f7d441d995559143f4861d62e98plougher } 539476dcb48b24efff22caa970f000e151f1b28918dplougher 5406f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 54188facddfd83e48a907b82210ddccbb4f84d80aecplougher 542d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, 543d4204758f77acb5a371fa1487a755b76a05d5476plougher t->tm_mday, t->tm_hour, t->tm_min, pathname); 5446f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 5456f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 5463edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 5473edfa57b6a463f7d441d995559143f4861d62e98plougher 548476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 549476dcb48b24efff22caa970f000e151f1b28918dplougher} 550476dcb48b24efff22caa970f000e151f1b28918dplougher 551443c15812032991c98b33b5424b17bcd55fe3575plougher 552e3206fad5b70e7e0527db2a627ad26616a8a2429ploughervoid add_entry(struct hash_table_entry *hash_table[], long long start, 553e3206fad5b70e7e0527db2a627ad26616a8a2429plougher int bytes) 554443c15812032991c98b33b5424b17bcd55fe3575plougher{ 555443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 556443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 557443c15812032991c98b33b5424b17bcd55fe3575plougher 558cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher hash_table_entry = malloc(sizeof(struct hash_table_entry)); 559cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher if(hash_table_entry == NULL) 5604a39fa82d4614c18d2977be7898d78d20ba01a49plougher EXIT_UNSQUASH("Out of memory in add_entry\n"); 561443c15812032991c98b33b5424b17bcd55fe3575plougher 562443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 563443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 564443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 565443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 566443c15812032991c98b33b5424b17bcd55fe3575plougher} 567443c15812032991c98b33b5424b17bcd55fe3575plougher 568443c15812032991c98b33b5424b17bcd55fe3575plougher 569f404f4914fdb272a70e18664e8963d793cc90f44plougherint lookup_entry(struct hash_table_entry *hash_table[], long long start) 570443c15812032991c98b33b5424b17bcd55fe3575plougher{ 571443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 572443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 573443c15812032991c98b33b5424b17bcd55fe3575plougher 5749dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 5759dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 5767a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher 577443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 578443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 579443c15812032991c98b33b5424b17bcd55fe3575plougher 580443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 581443c15812032991c98b33b5424b17bcd55fe3575plougher} 582443c15812032991c98b33b5424b17bcd55fe3575plougher 583443c15812032991c98b33b5424b17bcd55fe3575plougher 5843306cb2b54a60a32664617118336ac141e1471b6plougherint read_fs_bytes(int fd, long long byte, int bytes, void *buff) 585443c15812032991c98b33b5424b17bcd55fe3575plougher{ 586443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 587d7f3de3408089ce187d8bc26f6072730c77628daplougher int res, count; 588443c15812032991c98b33b5424b17bcd55fe3575plougher 589c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, 590c435240f52b78b0ef498118727ba8dad186db26bplougher bytes); 591fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 592443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 5935d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 594443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 595443c15812032991c98b33b5424b17bcd55fe3575plougher } 596443c15812032991c98b33b5424b17bcd55fe3575plougher 597d7f3de3408089ce187d8bc26f6072730c77628daplougher for(count = 0; count < bytes; count += res) { 598d7f3de3408089ce187d8bc26f6072730c77628daplougher res = read(fd, buff + count, bytes - count); 599d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res < 1) { 600d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res == 0) { 601e3206fad5b70e7e0527db2a627ad26616a8a2429plougher ERROR("Read on filesystem failed because " 602e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "EOF\n"); 603d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 604d7f3de3408089ce187d8bc26f6072730c77628daplougher } else if(errno != EINTR) { 605d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because %s\n", 606d7f3de3408089ce187d8bc26f6072730c77628daplougher strerror(errno)); 607d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 608d7f3de3408089ce187d8bc26f6072730c77628daplougher } else 609d7f3de3408089ce187d8bc26f6072730c77628daplougher res = 0; 610d7f3de3408089ce187d8bc26f6072730c77628daplougher } 611443c15812032991c98b33b5424b17bcd55fe3575plougher } 612443c15812032991c98b33b5424b17bcd55fe3575plougher 613443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 614443c15812032991c98b33b5424b17bcd55fe3575plougher} 615443c15812032991c98b33b5424b17bcd55fe3575plougher 616443c15812032991c98b33b5424b17bcd55fe3575plougher 617923b301e304637fd5e587eb05a6f44558abae2bdplougherint read_block(int fd, long long start, long long *next, void *block) 618443c15812032991c98b33b5424b17bcd55fe3575plougher{ 619443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 620443c15812032991c98b33b5424b17bcd55fe3575plougher int offset = 2; 621443c15812032991c98b33b5424b17bcd55fe3575plougher 622443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 623923b301e304637fd5e587eb05a6f44558abae2bdplougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 624fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 625923b301e304637fd5e587eb05a6f44558abae2bdplougher c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); 626443c15812032991c98b33b5424b17bcd55fe3575plougher } else 6273306cb2b54a60a32664617118336ac141e1471b6plougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 628fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 629fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 630d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, 631d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? 632d4204758f77acb5a371fa1487a755b76a05d5476plougher "compressed" : "uncompressed"); 633443c15812032991c98b33b5424b17bcd55fe3575plougher 63427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) 635443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 636443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED(c_byte)) { 637443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[SQUASHFS_METADATA_SIZE]; 638efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 639443c15812032991c98b33b5424b17bcd55fe3575plougher 640443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 64186561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start + offset, c_byte, buffer) == FALSE) 642fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 643443c15812032991c98b33b5424b17bcd55fe3575plougher 644b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, buffer, c_byte, 645efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_METADATA_SIZE, &error); 646efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 647efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 648efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 649efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 650fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 651443c15812032991c98b33b5424b17bcd55fe3575plougher } 652443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 653443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 654efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 655443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 656443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 65786561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start + offset, c_byte, block) == FALSE) 658fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 659443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 660443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 661443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 662443c15812032991c98b33b5424b17bcd55fe3575plougher } 663fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 664fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 66568ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher ERROR("read_block: failed to read block @0x%llx\n", start); 666fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 667443c15812032991c98b33b5424b17bcd55fe3575plougher} 668443c15812032991c98b33b5424b17bcd55fe3575plougher 669443c15812032991c98b33b5424b17bcd55fe3575plougher 670443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 671443c15812032991c98b33b5424b17bcd55fe3575plougher{ 672efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 673443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 674443c15812032991c98b33b5424b17bcd55fe3575plougher 675d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, 676c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : 677c435240f52b78b0ef498118727ba8dad186db26bplougher "uncompressed"); 678fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 679443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 68086561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, data) == FALSE) 68168ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 682443c15812032991c98b33b5424b17bcd55fe3575plougher 683b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, data, c_byte, 684b48442b2e37b3cb7efbffb032968f115eec7963cplougher block_size, &error); 685efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 686efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 687efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 688efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 68968ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 690443c15812032991c98b33b5424b17bcd55fe3575plougher } 691443c15812032991c98b33b5424b17bcd55fe3575plougher 692efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 693443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 69486561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, block) == FALSE) 69568ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 696443c15812032991c98b33b5424b17bcd55fe3575plougher 697443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 698443c15812032991c98b33b5424b17bcd55fe3575plougher } 69968ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher 70068ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougherfailed: 701d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, 702c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte); 70368ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher return FALSE; 704443c15812032991c98b33b5424b17bcd55fe3575plougher} 705443c15812032991c98b33b5424b17bcd55fe3575plougher 706443c15812032991c98b33b5424b17bcd55fe3575plougher 70702bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_inode_table(long long start, long long end) 708443c15812032991c98b33b5424b17bcd55fe3575plougher{ 709443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 710443c15812032991c98b33b5424b17bcd55fe3575plougher 71141da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); 712443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 713c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 714c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher inode_table = realloc(inode_table, size += 715c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher SQUASHFS_METADATA_SIZE); 716c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(inode_table == NULL) 717c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher EXIT_UNSQUASH("Out of memory in " 718c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher "uncompress_inode_table"); 719c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher } 720443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_inode_table: reading block 0x%llx\n", start); 721443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 722176b325add10f6b9846f771f75d8543364d4c121plougher res = read_block(fd, start, &start, inode_table + bytes); 723c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) { 724443c15812032991c98b33b5424b17bcd55fe3575plougher free(inode_table); 725d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_inode_table: failed to read " 726d4204758f77acb5a371fa1487a755b76a05d5476plougher "block \n"); 727443c15812032991c98b33b5424b17bcd55fe3575plougher } 728443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 729443c15812032991c98b33b5424b17bcd55fe3575plougher } 730443c15812032991c98b33b5424b17bcd55fe3575plougher} 731443c15812032991c98b33b5424b17bcd55fe3575plougher 732443c15812032991c98b33b5424b17bcd55fe3575plougher 733d4204758f77acb5a371fa1487a755b76a05d5476plougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, 734fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher unsigned int xattr, unsigned int set_mode) 735443c15812032991c98b33b5424b17bcd55fe3575plougher{ 7366f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 737443c15812032991c98b33b5424b17bcd55fe3575plougher 7382ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, xattr); 7392ef25cb004cc6995bd36f781863aa844fe8c358dplougher 740443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 741d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to set time on %s, because %s\n", 742d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 743443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 744443c15812032991c98b33b5424b17bcd55fe3575plougher } 745443c15812032991c98b33b5424b17bcd55fe3575plougher 7469dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 7476f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 748c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("set_attributes: failed to change uid and gids " 749c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s, because %s\n", pathname, 750c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 751443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 752443c15812032991c98b33b5424b17bcd55fe3575plougher } 7539dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 7549dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 7559dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 7569dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 757d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change mode %s, because %s\n", 758d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 7599dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 760443c15812032991c98b33b5424b17bcd55fe3575plougher } 761443c15812032991c98b33b5424b17bcd55fe3575plougher 762443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 763443c15812032991c98b33b5424b17bcd55fe3575plougher} 764443c15812032991c98b33b5424b17bcd55fe3575plougher 765443c15812032991c98b33b5424b17bcd55fe3575plougher 7661c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougherint write_bytes(int fd, char *buff, int bytes) 7671c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher{ 7681c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher int res, count; 7691c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7701c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher for(count = 0; count < bytes; count += res) { 7711c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = write(fd, buff + count, bytes - count); 7721c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(res == -1) { 7731c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(errno != EINTR) { 774c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Write on output file failed because " 775c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", strerror(errno)); 7761c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return -1; 7771c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7781c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = 0; 7791c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7801c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7811c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7821c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return 0; 7831c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher} 7841c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7851c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 786b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 787c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherchar *zero_data = NULL; 788b9cee889506e674726856035dba52d5e1cceeb99plougher 78987f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougherint write_block(int file_fd, char *buffer, int size, long long hole, int sparse) 790b9cee889506e674726856035dba52d5e1cceeb99plougher{ 791b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 792b9cee889506e674726856035dba52d5e1cceeb99plougher 793b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 794c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse && lseek_broken == FALSE) { 795c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error = lseek(file_fd, off, SEEK_CUR); 796c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == -1) 797c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher /* failed to seek beyond end of file */ 798c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher lseek_broken = TRUE; 799c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher } 800c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 801c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if((sparse == FALSE || lseek_broken) && zero_data == NULL) { 802b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 803c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("write_block: failed to alloc " 804c435240f52b78b0ef498118727ba8dad186db26bplougher "zero data block\n"); 805b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 806b9cee889506e674726856035dba52d5e1cceeb99plougher } 807c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 808c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse == FALSE || lseek_broken) { 809b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 810b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 811b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 812d4204758f77acb5a371fa1487a755b76a05d5476plougher avail_bytes = hole > block_size ? block_size : 813d4204758f77acb5a371fa1487a755b76a05d5476plougher hole; 814d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_bytes(file_fd, zero_data, avail_bytes) 815d4204758f77acb5a371fa1487a755b76a05d5476plougher == -1) 816b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 817b9cee889506e674726856035dba52d5e1cceeb99plougher } 818b9cee889506e674726856035dba52d5e1cceeb99plougher } 819b9cee889506e674726856035dba52d5e1cceeb99plougher } 820b9cee889506e674726856035dba52d5e1cceeb99plougher 8211c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(write_bytes(file_fd, buffer, size) == -1) 822b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 823b9cee889506e674726856035dba52d5e1cceeb99plougher 824b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 825b9cee889506e674726856035dba52d5e1cceeb99plougher 826b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 827b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 828b9cee889506e674726856035dba52d5e1cceeb99plougher} 829b9cee889506e674726856035dba52d5e1cceeb99plougher 8308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 831cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; 832cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_cond_t open_empty = PTHREAD_COND_INITIALIZER; 833cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_unlimited, open_count; 834cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#define OPEN_FILE_MARGIN 10 835cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 836cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 837cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid open_init(int count) 838cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 839cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count = count; 840cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_unlimited = count == -1; 841cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 842cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 843cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 844cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_wait(char *pathname, int flags, mode_t mode) 845cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 846cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 847cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 848cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher while (open_count == 0) 849cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_wait(&open_empty, &open_mutex); 850cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count --; 851cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 852cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 853cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 854cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher return open(pathname, flags, mode); 855cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 856cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 857cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 858cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid close_wake(int fd) 859cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 860cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close(fd); 861cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 862cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 863cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 864cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count ++; 865cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_signal(&open_empty); 866cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 867cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 868cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 869cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 870cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 8712c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_file(char *pathname, int file_fd, struct inode *inode) 8722c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 8732c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 8742c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 8752c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_file: unable to malloc file\n"); 8762c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 8772c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = file_fd; 8782c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->file_size = inode->data; 8792c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = inode->mode; 8802c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = inode->gid; 8812c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = inode->uid; 8822c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = inode->time; 8832c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 8842c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 8852c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->sparse = inode->sparse; 8862c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = inode->xattr; 8872c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 8882c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 8892c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 8902c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 8912c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_dir(char *pathname, struct dir *dir) 8922c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 8932c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 8942c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 8952c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_dir: unable to malloc file\n"); 8962c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 8972c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = -1; 8982c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = dir->mode; 8992c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = dir->guid; 9002c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = dir->uid; 9012c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = dir->mtime; 9022c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 9032c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = dir->xattr; 9042c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 9052c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 9062c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9072c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 90879df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 909443c15812032991c98b33b5424b17bcd55fe3575plougher{ 9108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 911f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 91279df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 91379df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 914443c15812032991c98b33b5424b17bcd55fe3575plougher 91579df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 916443c15812032991c98b33b5424b17bcd55fe3575plougher 917cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher file_fd = open_wait(pathname, O_CREAT | O_WRONLY | 918cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); 919d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file_fd == -1) { 920d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("write_file: failed to create file %s, because %s\n", 921d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 922443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 923443c15812032991c98b33b5424b17bcd55fe3575plougher } 924443c15812032991c98b33b5424b17bcd55fe3575plougher 9256037584bc3e861ff932f5244105959c56c8560e3plougher block_list = malloc(inode->blocks * sizeof(unsigned int)); 9266037584bc3e861ff932f5244105959c56c8560e3plougher if(block_list == NULL) 9278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 928443c15812032991c98b33b5424b17bcd55fe3575plougher 92979df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 930443c15812032991c98b33b5424b17bcd55fe3575plougher 931d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 932d4204758f77acb5a371fa1487a755b76a05d5476plougher * the writer thread is queued a squashfs_file structure describing the 933009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * file. If the file has one or more blocks or a fragment they are 934c435240f52b78b0ef498118727ba8dad186db26bplougher * queued separately (references to blocks in the cache). 935d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 9362c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_file(pathname, file_fd, inode); 937443c15812032991c98b33b5424b17bcd55fe3575plougher 93879df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 9398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 9408372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 9418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 9428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 9438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 9448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 945d4204758f77acb5a371fa1487a755b76a05d5476plougher block->size = i == file_end ? inode->data & (block_size - 1) : 946d4204758f77acb5a371fa1487a755b76a05d5476plougher block_size; 947009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher if(block_list[i] == 0) /* sparse block */ 9488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 9498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 950d4204758f77acb5a371fa1487a755b76a05d5476plougher block->buffer = cache_get(data_cache, start, 951d4204758f77acb5a371fa1487a755b76a05d5476plougher block_list[i]); 9528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 953443c15812032991c98b33b5424b17bcd55fe3575plougher } 9548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 955443c15812032991c98b33b5424b17bcd55fe3575plougher } 956443c15812032991c98b33b5424b17bcd55fe3575plougher 95779df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 9588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 9598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 9608372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 9618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 9628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 9638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 96479df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 9658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 96679df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 96779df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 9688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 969b9cee889506e674726856035dba52d5e1cceeb99plougher } 970b9cee889506e674726856035dba52d5e1cceeb99plougher 971b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 972443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 973443c15812032991c98b33b5424b17bcd55fe3575plougher} 974476dcb48b24efff22caa970f000e151f1b28918dplougher 975476dcb48b24efff22caa970f000e151f1b28918dplougher 9766f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 977443c15812032991c98b33b5424b17bcd55fe3575plougher{ 9786f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 979443c15812032991c98b33b5424b17bcd55fe3575plougher 9806f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 981443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 9826013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 9836013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 9846013a30bd39550decc2546a47e5168e57bfcfde8plougher 9856f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 986c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create hardlink, " 987c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", strerror(errno)); 988443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 989443c15812032991c98b33b5424b17bcd55fe3575plougher } 990443c15812032991c98b33b5424b17bcd55fe3575plougher 991443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 992443c15812032991c98b33b5424b17bcd55fe3575plougher } 993443c15812032991c98b33b5424b17bcd55fe3575plougher 9946f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 9956f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 9966f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 997c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("create_inode: regular file, file_size %lld, " 998c435240f52b78b0ef498118727ba8dad186db26bplougher "blocks %d\n", i->data, i->blocks); 999443c15812032991c98b33b5424b17bcd55fe3575plougher 100079df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 1001443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 1002443c15812032991c98b33b5424b17bcd55fe3575plougher break; 10036f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 100499ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSYMLINK_TYPE: 1005d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: symlink, symlink_size %lld\n", 1006d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data); 1007443c15812032991c98b33b5424b17bcd55fe3575plougher 1008a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1009a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1010a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 10116f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 1012c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create symlink " 1013c435240f52b78b0ef498118727ba8dad186db26bplougher "%s, because %s\n", pathname, 1014c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1015443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1016443c15812032991c98b33b5424b17bcd55fe3575plougher } 1017443c15812032991c98b33b5424b17bcd55fe3575plougher 10182ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, i->xattr); 10192ef25cb004cc6995bd36f781863aa844fe8c358dplougher 10209dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 10216f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 1022c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to change " 1023c435240f52b78b0ef498118727ba8dad186db26bplougher "uid and gids on %s, because " 1024c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", pathname, 1025c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1026443c15812032991c98b33b5424b17bcd55fe3575plougher } 1027443c15812032991c98b33b5424b17bcd55fe3575plougher 1028443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 1029443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1030443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 103199ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_CHRDEV_TYPE: 103299ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LBLKDEV_TYPE: 103399ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LCHRDEV_TYPE: { 10346f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 1035545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 1036443c15812032991c98b33b5424b17bcd55fe3575plougher 10379dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 1038a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1039a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1040a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 10416f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 1042d4204758f77acb5a371fa1487a755b76a05d5476plougher makedev((i->data >> 8) & 0xff, 1043d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data & 0xff)) == -1) { 1044c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create " 1045c435240f52b78b0ef498118727ba8dad186db26bplougher "%s device %s, because %s\n", 1046d4204758f77acb5a371fa1487a755b76a05d5476plougher chrdev ? "character" : "block", 1047d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 1048443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1049443c15812032991c98b33b5424b17bcd55fe3575plougher } 1050c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, 1051fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->gid, i->time, i->xattr, TRUE); 1052443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 1053443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1054c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: could not create %s " 1055c435240f52b78b0ef498118727ba8dad186db26bplougher "device %s, because you're not " 1056c435240f52b78b0ef498118727ba8dad186db26bplougher "superuser!\n", chrdev ? "character" : 1057c435240f52b78b0ef498118727ba8dad186db26bplougher "block", pathname); 1058443c15812032991c98b33b5424b17bcd55fe3575plougher break; 10596f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1060443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 106199ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LFIFO_TYPE: 1062443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 1063443c15812032991c98b33b5424b17bcd55fe3575plougher 1064a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1065a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1066a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 1067443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 1068d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create fifo %s, " 1069d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, 1070d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 1071443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1072443c15812032991c98b33b5424b17bcd55fe3575plougher } 1073c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, i->gid, 1074fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->time, i->xattr, TRUE); 1075443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 1076443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1077443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 107899ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSOCKET_TYPE: 1079443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 1080443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 1081443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1082443c15812032991c98b33b5424b17bcd55fe3575plougher default: 1083d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Unknown inode type %d in create_inode_table!\n", 1084d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type); 1085443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1086443c15812032991c98b33b5424b17bcd55fe3575plougher } 1087fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 10886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 1089443c15812032991c98b33b5424b17bcd55fe3575plougher 1090443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1091443c15812032991c98b33b5424b17bcd55fe3575plougher} 1092443c15812032991c98b33b5424b17bcd55fe3575plougher 1093443c15812032991c98b33b5424b17bcd55fe3575plougher 109402bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_directory_table(long long start, long long end) 1095443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1096443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 1097443c15812032991c98b33b5424b17bcd55fe3575plougher 109841da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); 109941da3230b2ac91a73f9190676f66b3d80b21c270plougher 1100443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 110107d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 110207d4d0dcafeb198a568f859b88034637e6e7a8e7plougher directory_table = realloc(directory_table, size += 110307d4d0dcafeb198a568f859b88034637e6e7a8e7plougher SQUASHFS_METADATA_SIZE); 110407d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(directory_table == NULL) 110507d4d0dcafeb198a568f859b88034637e6e7a8e7plougher EXIT_UNSQUASH("Out of memory in " 110607d4d0dcafeb198a568f859b88034637e6e7a8e7plougher "uncompress_directory_table\n"); 110707d4d0dcafeb198a568f859b88034637e6e7a8e7plougher } 1108c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("uncompress_directory_table: reading block 0x%llx\n", 1109c435240f52b78b0ef498118727ba8dad186db26bplougher start); 1110443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 1111176b325add10f6b9846f771f75d8543364d4c121plougher res = read_block(fd, start, &start, directory_table + bytes); 1112c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) 1113c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("uncompress_directory_table: failed to " 1114c435240f52b78b0ef498118727ba8dad186db26bplougher "read block\n"); 1115443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 1116443c15812032991c98b33b5424b17bcd55fe3575plougher } 1117443c15812032991c98b33b5424b17bcd55fe3575plougher} 1118443c15812032991c98b33b5424b17bcd55fe3575plougher 1119443c15812032991c98b33b5424b17bcd55fe3575plougher 11209dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 11219dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1122443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1123443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1124443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1125443c15812032991c98b33b5424b17bcd55fe3575plougher 1126443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1127443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1128443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1129443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1130443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1131443c15812032991c98b33b5424b17bcd55fe3575plougher 1132443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1133443c15812032991c98b33b5424b17bcd55fe3575plougher} 1134443c15812032991c98b33b5424b17bcd55fe3575plougher 1135443c15812032991c98b33b5424b17bcd55fe3575plougher 1136443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1137443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1138443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1139443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1140443c15812032991c98b33b5424b17bcd55fe3575plougher} 1141443c15812032991c98b33b5424b17bcd55fe3575plougher 1142443c15812032991c98b33b5424b17bcd55fe3575plougher 114304281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougherchar *get_component(char *target, char **targname) 1144b54566f5c433764830c29c83151691d0034de094plougher{ 114504281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *start; 114604281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 1147b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 11483cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1149b54566f5c433764830c29c83151691d0034de094plougher 115004281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher start = target; 1151b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 115204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target ++; 1153b54566f5c433764830c29c83151691d0034de094plougher 115404281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher *targname = strndup(start, target - start); 1155b54566f5c433764830c29c83151691d0034de094plougher 1156b54566f5c433764830c29c83151691d0034de094plougher return target; 1157b54566f5c433764830c29c83151691d0034de094plougher} 1158b54566f5c433764830c29c83151691d0034de094plougher 1159b54566f5c433764830c29c83151691d0034de094plougher 11606ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 11616ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 11626ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 11636ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11646ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 11656ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 11666ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 11676ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 11686ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 11696ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 11706ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 11716ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 11726ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 11736ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11746ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 11756ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 11766ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11776ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11784dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1179b54566f5c433764830c29c83151691d0034de094plougher{ 118004281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *targname; 11814dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 118271add234b27054974d5e29f95b3fab3072792a62plougher 1183b7bb000643cd21c615a0366a7365441aa9c433f2plougher TRACE("add_path: adding \"%s\" extract file\n", target); 1184b7bb000643cd21c615a0366a7365441aa9c433f2plougher 118504281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target = get_component(target, &targname); 118671add234b27054974d5e29f95b3fab3072792a62plougher 118771add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 11889dd4507fac1c96098eda8abe699a813a59451633plougher paths = malloc(sizeof(struct pathname)); 11899dd4507fac1c96098eda8abe699a813a59451633plougher if(paths == NULL) 11904dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 11914dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 119271add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 119371add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 119471add234b27054974d5e29f95b3fab3072792a62plougher } 119571add234b27054974d5e29f95b3fab3072792a62plougher 119671add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 119771add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 119871add234b27054974d5e29f95b3fab3072792a62plougher break; 119971add234b27054974d5e29f95b3fab3072792a62plougher 12006ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 1201d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1202d4204758f77acb5a371fa1487a755b76a05d5476plougher * allocate new name entry 1203d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 120471add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 1205d4204758f77acb5a371fa1487a755b76a05d5476plougher paths->name = realloc(paths->name, (i + 1) * 1206d4204758f77acb5a371fa1487a755b76a05d5476plougher sizeof(struct path_entry)); 1207fd628227871aecb36bb2b4f9c7f664f731510cdeplougher if(paths->name == NULL) 1208fd628227871aecb36bb2b4f9c7f664f731510cdeplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 120904281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher paths->name[i].name = targname; 12106ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 12114dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 12124dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 12131f3cc42a2f77966d321a38d1709eba26f71104bdplougher if(paths->name[i].preg == NULL) 12141f3cc42a2f77966d321a38d1709eba26f71104bdplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 1215d4204758f77acb5a371fa1487a755b76a05d5476plougher error = regcomp(paths->name[i].preg, targname, 1216d4204758f77acb5a371fa1487a755b76a05d5476plougher REG_EXTENDED|REG_NOSUB); 1217545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 121862859d215e7f828ace8501f5863f0c3d8b48ebf3Phillip Lougher char str[1024]; /* overflow safe */ 12194dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 12204dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 1221d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("invalid regex %s in export %s, " 1222c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", targname, alltarget, 1223c435240f52b78b0ef498118727ba8dad186db26bplougher str); 12244dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 12254dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 12264dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 12276ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12286ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 1229d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1230d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component 1231d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 123271add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 123371add234b27054974d5e29f95b3fab3072792a62plougher else 1234d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1235d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1236d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 12374dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 12386ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 1239d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1240d4204758f77acb5a371fa1487a755b76a05d5476plougher * existing matching entry 1241d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 124204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher free(targname); 124304281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 12446ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 1245d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1246c435240f52b78b0ef498118727ba8dad186db26bplougher * No sub-directory which means this is the leaf 1247c435240f52b78b0ef498118727ba8dad186db26bplougher * component of a pre-existing extract which subsumes 1248c435240f52b78b0ef498118727ba8dad186db26bplougher * the extract currently being added, in which case stop 1249c435240f52b78b0ef498118727ba8dad186db26bplougher * adding components 1250d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 12516ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 1252d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1253d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component and child components exist 1254c435240f52b78b0ef498118727ba8dad186db26bplougher * from more specific extracts, delete as they're 1255c435240f52b78b0ef498118727ba8dad186db26bplougher * subsumed by this extract 1256d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 12576ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 12586ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 12596ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 1260d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1261d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1262d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 12636ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 126471add234b27054974d5e29f95b3fab3072792a62plougher } 126571add234b27054974d5e29f95b3fab3072792a62plougher 126671add234b27054974d5e29f95b3fab3072792a62plougher return paths; 126771add234b27054974d5e29f95b3fab3072792a62plougher} 12686ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12696ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1270a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 127171add234b27054974d5e29f95b3fab3072792a62plougher{ 12728372232d2460411adaa2299c32a0a88665e44902plougher struct pathnames *new = malloc(sizeof(struct pathnames)); 1273c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher if(new == NULL) 1274c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher EXIT_UNSQUASH("Out of memory in init_subdir\n"); 1275a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1276a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1277a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1278a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1279a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1280a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1281a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 12823488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths->count % PATHS_ALLOC_SIZE == 0) { 1283d4204758f77acb5a371fa1487a755b76a05d5476plougher paths = realloc(paths, sizeof(struct pathnames *) + 12843488d3bb3b89c394534ad2be909b661771a9581bplougher (paths->count + PATHS_ALLOC_SIZE) * 12853488d3bb3b89c394534ad2be909b661771a9581bplougher sizeof(struct pathname *)); 12863488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths == NULL) 12873488d3bb3b89c394534ad2be909b661771a9581bplougher EXIT_UNSQUASH("Out of memory in add_subdir\n"); 12883488d3bb3b89c394534ad2be909b661771a9581bplougher } 1289a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1290a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1291a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1292a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1293a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1294a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1295a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1296a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1297a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1298a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1299a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1300a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1301a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1302a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1303a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 130471add234b27054974d5e29f95b3fab3072792a62plougher 130571add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 130671add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1307b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 130871add234b27054974d5e29f95b3fab3072792a62plougher } 130971add234b27054974d5e29f95b3fab3072792a62plougher 1310a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1311a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1312a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1313a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1314a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1315a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1316c435240f52b78b0ef498118727ba8dad186db26bplougher regexec(path->name[i].preg, name, (size_t) 0, 1317c435240f52b78b0ef498118727ba8dad186db26bplougher NULL, 0) == 0 : fnmatch(path->name[i].name, 1318c435240f52b78b0ef498118727ba8dad186db26bplougher name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 1319c435240f52b78b0ef498118727ba8dad186db26bplougher 0; 1320a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1321d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1322d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a leaf component, any subdirectories 1323c435240f52b78b0ef498118727ba8dad186db26bplougher * will implicitly match, therefore return an 1324c435240f52b78b0ef498118727ba8dad186db26bplougher * empty new search set 1325d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1326a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1327a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1328a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1329d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1330d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a non-leaf component, add any 1331c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to the new set of 1332c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to scan for this name 1333d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1334a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1335a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1336a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1337b54566f5c433764830c29c83151691d0034de094plougher 1338a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1339d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1340d4204758f77acb5a371fa1487a755b76a05d5476plougher * no matching names found, delete empty search set, and return 1341d4204758f77acb5a371fa1487a755b76a05d5476plougher * FALSE 1342d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1343a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1344a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1345a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1346a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1347a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1348d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 13490a0d045642e8e413f90b770539193d3fd1522786plougher * one or more matches with sub-directories found (no leaf matches), 13500a0d045642e8e413f90b770539193d3fd1522786plougher * return new search set and return TRUE 13510a0d045642e8e413f90b770539193d3fd1522786plougher */ 1352a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1353a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1354a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 1355d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1356d4204758f77acb5a371fa1487a755b76a05d5476plougher * found matching leaf exclude, return empty search set and return TRUE 1357d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1358a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1359a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1360a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1361b54566f5c433764830c29c83151691d0034de094plougher} 1362b54566f5c433764830c29c83151691d0034de094plougher 1363b54566f5c433764830c29c83151691d0034de094plougher 1364b807ab3497c01a49fed6f9daafce3bfc599a9421ploughervoid pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1365d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1366eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1367eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 1368454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *name; 1369eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 1370eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1371eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1372eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1373cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) 1374cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1375cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1376eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1377eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1378454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *pathname; 1379454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher int res; 1380eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1381d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", 1382d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1383eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1384eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 1385eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1386eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1387454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1388454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher if(res == -1) 1389454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1390eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1391eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 1392eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 1393eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 1394d4204758f77acb5a371fa1487a755b76a05d5476plougher if(type == SQUASHFS_FILE_TYPE || 1395d4204758f77acb5a371fa1487a755b76a05d5476plougher type == SQUASHFS_LREG_TYPE) { 1396312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 1397eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 1398d4204758f77acb5a371fa1487a755b76a05d5476plougher created_inode[i->inode_number - 1] = 1399d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) i; 1400d4204758f77acb5a371fa1487a755b76a05d5476plougher total_blocks += (i->data + 1401d4204758f77acb5a371fa1487a755b76a05d5476plougher (block_size - 1)) >> block_log; 1402eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1403eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 1404eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1405eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 1406eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1407eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1408eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 1409454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher free(pathname); 1410eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1411eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1412eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 1413eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1414eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1415eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1416a2cff53655359b044ea88baa76cb16d1c8f44d2aploughervoid dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1417d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1418443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1419443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1420d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *name; 1421a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 1422eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1423eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1424443c15812032991c98b33b5424b17bcd55fe3575plougher 1425cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) { 1426cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher ERROR("dir_scan: failed to read directory %s, skipping\n", 1427cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher parent_name); 1428cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1429cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher } 1430cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1431eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 1432eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 1433eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 14342c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!lsonly) { 14352c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 14362c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Make directory with default User rwx permissions rather than 14372c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * the permissions from the filesystem, as these may not have 14382c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * write/execute permission. These are fixed up later in 14392c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * set_attributes(). 14402c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 14412c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher int res = mkdir(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 14422c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(res == -1) { 14432c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 14442c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Skip directory if mkdir fails, unless we're 14452c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * forcing and the error is -EEXIST 14462c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 14472c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!force || errno != EEXIST) { 14482c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to make directory %s, " 14492c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "because %s\n", parent_name, 14502c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher strerror(errno)); 14512c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher squashfs_closedir(dir); 14522c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher return; 14532c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 14542c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 14552c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 14562c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Try to change permissions of existing directory so 14572c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * that we can write to it 14582c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 14592c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher res = chmod(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 14602c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if (res == -1) 14612c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to change permissions " 14622c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "for directory %s, because %s\n", 14632c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher parent_name, strerror(errno)); 14642c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 146585917a285edbd4bb78f1b245f66c634d1e0d4029plougher } 1466443c15812032991c98b33b5424b17bcd55fe3575plougher 1467443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1468d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *pathname; 1469d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher int res; 1470d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher 1471d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", 1472d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1473b54566f5c433764830c29c83151691d0034de094plougher 147471add234b27054974d5e29f95b3fab3072792a62plougher 147571add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 1476b54566f5c433764830c29c83151691d0034de094plougher continue; 1477b54566f5c433764830c29c83151691d0034de094plougher 1478d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1479d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher if(res == -1) 1480d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1481fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1482443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 148371add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 1484a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher else if(new == NULL) { 1485312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 14866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 14876f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 14886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 14896f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1490eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!lsonly) { 14916f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 1492eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher update_progress_bar(); 1493eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1494427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher 1495d4204758f77acb5a371fa1487a755b76a05d5476plougher if(i->type == SQUASHFS_SYMLINK_TYPE || 1496d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type == SQUASHFS_LSYMLINK_TYPE) 1497427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher free(i->symlink); 14986f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1499a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1500a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 1501d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher free(pathname); 1502443c15812032991c98b33b5424b17bcd55fe3575plougher } 1503443c15812032991c98b33b5424b17bcd55fe3575plougher 1504074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 15052c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_dir(parent_name, dir); 1506443c15812032991c98b33b5424b17bcd55fe3575plougher 1507443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 1508443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 1509443c15812032991c98b33b5424b17bcd55fe3575plougher} 1510443c15812032991c98b33b5424b17bcd55fe3575plougher 1511443c15812032991c98b33b5424b17bcd55fe3575plougher 1512b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 1513b624936abba03d38b7e9245c647339d8f6f34274plougher{ 151427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher time_t mkfs_time = (time_t) sBlk.s.mkfs_time; 1515b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 1516b624936abba03d38b7e9245c647339d8f6f34274plougher 1517b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 1518d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 151927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "little endian " : 152027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1521b624936abba03d38b7e9245c647339d8f6f34274plougher#else 1522d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 152327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "big endian " : 152427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1525b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 1526c766500607f1ea7494b8360409be3d8ea66f9761plougher 1527d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : 1528d4204758f77acb5a371fa1487a755b76a05d5476plougher "failed to get time\n"); 1529e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", 1530e3206fad5b70e7e0527db2a627ad26616a8a2429plougher sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / 1531e3206fad5b70e7e0527db2a627ad26616a8a2429plougher (1024.0 * 1024.0)); 1532c766500607f1ea7494b8360409be3d8ea66f9761plougher 153327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 1534e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Compression %s\n", comp->name); 1535c766500607f1ea7494b8360409be3d8ea66f9761plougher 153627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Block size %d\n", sBlk.s.block_size); 1537d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem is %sexportable via NFS\n", 153827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); 1539d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Inodes are %scompressed\n", 154027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); 1541d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Data is %scompressed\n", 154227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); 1543c766500607f1ea7494b8360409be3d8ea66f9761plougher 15447ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(sBlk.s.s_major > 1) { 15457ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) 15467ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are not stored\n"); 15477ca09d1320cdc30a068f179b93ca5c141b55c395plougher else { 15487ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are %scompressed\n", 15497ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? 15507ca09d1320cdc30a068f179b93ca5c141b55c395plougher "un" : ""); 15517ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Always_use_fragments option is %sspecified\n", 15527ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : 15537ca09d1320cdc30a068f179b93ca5c141b55c395plougher "not "); 15547ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 15557ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 15567ca09d1320cdc30a068f179b93ca5c141b55c395plougher 1557de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(sBlk.s.s_major == 4) { 1558de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) 1559de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are not stored\n"); 1560de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher else 1561de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are %scompressed\n", 1562de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? 1563de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher "un" : ""); 1564de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher } 1565de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher 1566ba95dd35ef0e9f618d926ddc1a595076adc23818plougher if(sBlk.s.s_major < 4) 1567ba95dd35ef0e9f618d926ddc1a595076adc23818plougher printf("Check data is %spresent in the filesystem\n", 1568ba95dd35ef0e9f618d926ddc1a595076adc23818plougher SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : 1569ba95dd35ef0e9f618d926ddc1a595076adc23818plougher "not "); 1570c766500607f1ea7494b8360409be3d8ea66f9761plougher 157127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 1572d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Duplicates are %sremoved\n", 157327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); 15740337de3977eec74e6a3d28e0d0863299246de8b7plougher else 15750337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 1576c766500607f1ea7494b8360409be3d8ea66f9761plougher 157727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 157827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of fragments %d\n", sBlk.s.fragments); 1579c766500607f1ea7494b8360409be3d8ea66f9761plougher 158027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of inodes %d\n", sBlk.s.inodes); 1581c766500607f1ea7494b8360409be3d8ea66f9761plougher 158227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 158327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of ids %d\n", sBlk.s.no_ids); 15840f74340e3b68533339adc60f418ddf59fa188f61plougher else { 15850f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of uids %d\n", sBlk.no_uids); 15860f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of gids %d\n", sBlk.no_guids); 15870f74340e3b68533339adc60f418ddf59fa188f61plougher } 1588b624936abba03d38b7e9245c647339d8f6f34274plougher 158927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); 159027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.directory_table_start 0x%llx\n", 159127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 1592c766500607f1ea7494b8360409be3d8ea66f9761plougher 15930ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 1) 15940ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", 15950ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.fragment_table_start); 15960ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 15970ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 2) 15980ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.lookup_table_start 0x%llx\n\n", 15990ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.lookup_table_start); 16000ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 1601053da34003852e494400c1ade35b526e1821b576plougher if(sBlk.s.s_major == 4) { 160227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); 1603053da34003852e494400c1ade35b526e1821b576plougher TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", 1604053da34003852e494400c1ade35b526e1821b576plougher sBlk.s.xattr_id_table_start); 1605053da34003852e494400c1ade35b526e1821b576plougher } else { 16060f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 16070f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); 16080f74340e3b68533339adc60f418ddf59fa188f61plougher } 1609b624936abba03d38b7e9245c647339d8f6f34274plougher} 1610b624936abba03d38b7e9245c647339d8f6f34274plougher 1611b624936abba03d38b7e9245c647339d8f6f34274plougher 161202bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 1613443c15812032991c98b33b5424b17bcd55fe3575plougher{ 16146490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block_3 sBlk_3; 161564e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher struct squashfs_super_block sBlk_4; 16166490378e5b5e8dc058daf28423a7465699a6ba7bplougher 16176490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 16186490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Try to read a Squashfs 4 superblock 16196490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 162064e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), 16213306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_4); 162254660e177ba40ab08ee2f3304b9f030eb5675677plougher swap = sBlk_4.s_magic != SQUASHFS_MAGIC; 16236490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); 16246490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1625d4204758f77acb5a371fa1487a755b76a05d5476plougher if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && 1626d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk_4.s_minor == 0) { 16276490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.squashfs_opendir = squashfs_opendir_4; 16286490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment = read_fragment_4; 16296490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment_table = read_fragment_table_4; 16306490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_block_list = read_block_list_2; 16316490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_inode = read_inode_4; 16326490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_uids_guids = read_uids_guids_4; 16336490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); 1634efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1635efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 1636efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher * Check the compression type 1637efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 163827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher comp = lookup_compressor_id(sBlk.s.compression); 16396490378e5b5e8dc058daf28423a7465699a6ba7bplougher return TRUE; 16406490378e5b5e8dc058daf28423a7465699a6ba7bplougher } 16416490378e5b5e8dc058daf28423a7465699a6ba7bplougher 16426490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 16436490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock 16446490378e5b5e8dc058daf28423a7465699a6ba7bplougher * (compatible with 1 and 2 filesystems) 16456490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 164686561909d9ca51a4e4ce4efcfea30b41d1d08275plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), 16473306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_3); 1648443c15812032991c98b33b5424b17bcd55fe3575plougher 1649d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1650d4204758f77acb5a371fa1487a755b76a05d5476plougher * Check it is a SQUASHFS superblock 1651d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1652443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 165321ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic != SQUASHFS_MAGIC) { 165421ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { 16557a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher squashfs_super_block_3 sblk; 1656c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Reading a different endian SQUASHFS filesystem " 1657c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s\n", source); 16586490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); 16596490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); 1660443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 1661443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 1662c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Can't find a SQUASHFS superblock on %s\n", 1663c435240f52b78b0ef498118727ba8dad186db26bplougher source); 1664443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1665443c15812032991c98b33b5424b17bcd55fe3575plougher } 1666443c15812032991c98b33b5424b17bcd55fe3575plougher } 1667443c15812032991c98b33b5424b17bcd55fe3575plougher 166827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_magic = sBlk_3.s_magic; 166927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inodes = sBlk_3.inodes; 167027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.mkfs_time = sBlk_3.mkfs_time; 167127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size; 167227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragments = sBlk_3.fragments; 167327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_log = sBlk_3.block_log; 167427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.flags = sBlk_3.flags; 167527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major = sBlk_3.s_major; 167627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor = sBlk_3.s_minor; 167727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.root_inode = sBlk_3.root_inode; 167827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used; 167927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start; 168027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start; 168127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; 168227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; 16836490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_uids = sBlk_3.no_uids; 16846490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_guids = sBlk_3.no_guids; 16856490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start; 16866490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start; 168727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 16886490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1689443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 169027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { 169127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used_2; 16926490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start_2; 16936490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start_2; 169427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; 169527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; 169602bc3bcabf2b219f63961f07293b83629948f026plougher 169727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1) { 169827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size_1; 169927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk.uid_start; 1700ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1701ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 1702ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 17036f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 170479e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1705ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 170627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = 1707c435240f52b78b0ef498118727ba8dad186db26bplougher sBlk_3.fragment_table_start_2; 1708ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1709ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 1710ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 1711ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 17126f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 171379e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1714ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 171527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher } else if(sBlk.s.s_major == 3) { 1716ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_3; 1717ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment = read_fragment_3; 1718ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment_table = read_fragment_table_3; 1719ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 1720ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_inode = read_inode_3; 172179e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 172202bc3bcabf2b219f63961f07293b83629948f026plougher } else { 172327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, 172427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor); 17254c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 1726443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1727443c15812032991c98b33b5424b17bcd55fe3575plougher } 1728443c15812032991c98b33b5424b17bcd55fe3575plougher 1729efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 173099c8abf4de4297b3159355a0cefe9ad6f5182827plougher * 1.x, 2.x and 3.x filesystems use gzip compression. 1731efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 1732efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp = lookup_compressor("gzip"); 1733443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1734443c15812032991c98b33b5424b17bcd55fe3575plougher 1735443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 1736443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1737443c15812032991c98b33b5424b17bcd55fe3575plougher} 1738443c15812032991c98b33b5424b17bcd55fe3575plougher 1739443c15812032991c98b33b5424b17bcd55fe3575plougher 1740a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 174171add234b27054974d5e29f95b3fab3072792a62plougher{ 174271add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 1743afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher char buffer[MAX_LINE + 1]; /* overflow safe */ 1744e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher char *name; 174571add234b27054974d5e29f95b3fab3072792a62plougher 174663e21ee4b795bb900f82c18e7b5c6f7369907360plougher fd = fopen(filename, "r"); 174763e21ee4b795bb900f82c18e7b5c6f7369907360plougher if(fd == NULL) 1748e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Failed to open extract file \"%s\" because %s\n", 1749e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 1750e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1751afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher while(fgets(name = buffer, MAX_LINE + 1, fd) != NULL) { 1752e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher int len = strlen(name); 1753e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1754afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher if(len == MAX_LINE && name[len - 1] != '\n') 1755e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* line too large */ 1756e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Line too long when reading " 1757afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher "extract file \"%s\", larger than %d " 1758afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher "bytes\n", MAX_LINE, filename); 1759e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1760e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* 1761e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * Remove '\n' terminator if it exists (the last line 1762e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * in the file may not be '\n' terminated) 1763e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1764e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(len && name[len - 1] == '\n') 1765e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name[len - 1] = '\0'; 1766e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1767e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* Skip any leading whitespace */ 1768e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher while(isspace(*name)) 1769e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1770e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1771e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if comment line, skip */ 1772e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '#') 1773e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 1774e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1775e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* check for initial backslash, to accommodate 1776e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * filenames with leading space or leading # character 1777e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1778e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\\') 1779e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1780e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1781e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if line is now empty after skipping characters, skip it */ 1782e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\0') 1783e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 178471add234b27054974d5e29f95b3fab3072792a62plougher 1785a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 1786e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher } 1787e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1788e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(ferror(fd)) 1789e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Reading extract file \"%s\" failed because %s\n", 1790e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 179171add234b27054974d5e29f95b3fab3072792a62plougher 179271add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 1793a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 179471add234b27054974d5e29f95b3fab3072792a62plougher} 179571add234b27054974d5e29f95b3fab3072792a62plougher 179671add234b27054974d5e29f95b3fab3072792a62plougher 1797d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1798d4204758f77acb5a371fa1487a755b76a05d5476plougher * reader thread. This thread processes read requests queued by the 1799d4204758f77acb5a371fa1487a755b76a05d5476plougher * cache_get() routine. 1800d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18018888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 18028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 18038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 18048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 180586561909d9ca51a4e4ce4efcfea30b41d1d08275plougher int res = read_fs_bytes(fd, entry->block, 18068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 18078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 18088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 1810d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1811c435240f52b78b0ef498118727ba8dad186db26bplougher * queue successfully read block to the deflate 1812c435240f52b78b0ef498118727ba8dad186db26bplougher * thread(s) for further processing 1813d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_deflate, entry); 18158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1816d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1817d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has either been successfully read and is 1818d4204758f77acb5a371fa1487a755b76a05d5476plougher * uncompressed, or an error has occurred, clear pending 1819c435240f52b78b0ef498118727ba8dad186db26bplougher * flag, set error appropriately, and wake up any 1820c435240f52b78b0ef498118727ba8dad186db26bplougher * threads waiting on this buffer 1821d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 18238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 18258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1827d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1828d4204758f77acb5a371fa1487a755b76a05d5476plougher * writer thread. This processes file write requests queued by the 1829d4204758f77acb5a371fa1487a755b76a05d5476plougher * write_file() routine. 1830d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 18318888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 18328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 18338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 18348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 18368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 18378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 183887f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougher long long hole = 0; 183927636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 1840c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error; 18418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 18438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 18448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 18452c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } else if(file->fd == -1) { 18462c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* write attributes for directory file->pathname */ 18472c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher set_attributes(file->pathname, file->mode, file->uid, 18482c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid, file->time, file->xattr, TRUE); 18492c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file->pathname); 18502c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file); 18512c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher continue; 18528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 18558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 18578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1858eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 18598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 18608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 18628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 18638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 18648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 18658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 186827636cb2cec37a68313f9eb825c0548245eecad0plougher 186927636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 187027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 187127636cb2cec37a68313f9eb825c0548245eecad0plougher 1872c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(failed) 1873c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher continue; 1874c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1875c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher error = write_block(file_fd, block->buffer->data + 1876c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher block->offset, block->size, hole, file->sparse); 1877c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1878c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == FALSE) { 1879d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write data block %d\n", 1880d4204758f77acb5a371fa1487a755b76a05d5476plougher i); 188127636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 18828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 1883c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 18848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 18858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 18868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 18878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 188927636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 1890d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1891d4204758f77acb5a371fa1487a755b76a05d5476plougher * corner case for hole extending to end of file 1892d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1893d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file->sparse == FALSE || 1894d4204758f77acb5a371fa1487a755b76a05d5476plougher lseek(file_fd, hole, SEEK_CUR) == -1) { 1895d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1896d4204758f77acb5a371fa1487a755b76a05d5476plougher * for files which we don't want to write 1897c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * sparsely, or for broken lseeks which cannot 1898c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * seek beyond end of file, write_block will do 1899c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * the right thing 1900c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher */ 19018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 1902d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_block(file_fd, "\0", 1, hole, 1903d4204758f77acb5a371fa1487a755b76a05d5476plougher file->sparse) == FALSE) { 1904d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse " 1905d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 190627636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 19078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 1909d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse data " 1910d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 191127636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 19128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1915cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close_wake(file_fd); 191627636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 1917d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(file->pathname, file->mode, file->uid, 1918fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher file->gid, file->time, file->xattr, force); 191927636cb2cec37a68313f9eb825c0548245eecad0plougher else { 192027636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 192127636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 192227636cb2cec37a68313f9eb825c0548245eecad0plougher } 192379df93becb68081effabebba3006c794be308598plougher free(file->pathname); 19248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 192527636cb2cec37a68313f9eb825c0548245eecad0plougher 19268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 19288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1930d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1931d4204758f77acb5a371fa1487a755b76a05d5476plougher * decompress thread. This decompresses buffers queued by the read thread 1932d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 19338888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *deflator(void *arg) 19348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 19358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 19368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 19388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_deflate); 1939efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 1940efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1941b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, tmp, entry->data, 1942efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, 1943efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher &error); 1944efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1945efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) 1946efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 1947efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 1948efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher else 1949efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher memcpy(entry->data, tmp, res); 19508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1951d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1952d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has been either successfully decompressed, or an error 19538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 1954d4204758f77acb5a371fa1487a755b76a05d5476plougher * wake up any threads waiting on this block 1955d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1956efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher cache_block_ready(entry, res == -1); 19578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 19598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1961eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 1962eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1963eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timeval timeval; 1964eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timespec timespec; 19651b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 19661b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 19671b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 19681b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 196901b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher if(isatty(STDOUT_FILENO)) 197001b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 197101b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher "columns\n"); 19721b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 19731b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 19741b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 19751b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 19761b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 19771b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 19781b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 19791b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 19801b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 19811b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 19821b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 1983eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1984eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_init(&progress_wait, NULL); 1985eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 19861b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 1987eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 1988eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher gettimeofday(&timeval, NULL); 1989eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec = timeval.tv_sec; 1990eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(timeval.tv_usec + 250000 > 999999) 1991eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec++; 1992c435240f52b78b0ef498118727ba8dad186db26bplougher timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1993c435240f52b78b0ef498118727ba8dad186db26bplougher 1000; 1994c435240f52b78b0ef498118727ba8dad186db26bplougher pthread_cond_timedwait(&progress_wait, &screen_mutex, 1995c435240f52b78b0ef498118727ba8dad186db26bplougher ×pec); 19961b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress_enabled) 19971b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 1998d4204758f77acb5a371fa1487a755b76a05d5476plougher fifo_count + cur_blocks, total_inodes - 1999d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks, columns); 2000eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2001eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2002eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2003eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 20048888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 20058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2006cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher struct rlimit rlim; 2007cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher int i, max_files, res; 20088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 20098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 20118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGINT); 20128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 20138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 2014c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 2015c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 20168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 20188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 20198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 20208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 20218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 20238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 20248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 20258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 20268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 20278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 20288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 2030d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Failed to get number of available processors. " 2031d4204758f77acb5a371fa1487a755b76a05d5476plougher "Defaulting to 1\n"); 20328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 20338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 20359cc26b77a61fefdeb45f5c487c2bfdefd394b66fplougher processors = sysconf(_SC_NPROCESSORS_ONLN); 20368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 20378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20396697cff2155192a3e0c182a3cef046ebf215ac32plougher thread = malloc((3 + processors) * sizeof(pthread_t)); 20406697cff2155192a3e0c182a3cef046ebf215ac32plougher if(thread == NULL) 20418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 2042eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher deflator_thread = &thread[3]; 20438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2044cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2045cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * dimensioning the to_reader and to_deflate queues. The size of 2046cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * these queues is directly related to the amount of block 2047cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * read-ahead possible. To_reader queues block read requests to 2048cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the reader thread and to_deflate queues block decompression 2049cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * requests to the deflate thread(s) (once the block has been read by 2050cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the reader thread). The amount of read-ahead is determined by 2051cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the combined size of the data_block and fragment caches which 2052cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * determine the total number of blocks which can be "in flight" 2053cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * at any one time (either being read or being decompressed) 2054cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2055cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * The maximum file open limit, however, affects the read-ahead 2056cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * possible, in that for normal sizes of the fragment and data block 2057cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches, where the incoming files have few data blocks or one fragment 2058cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * only, the file open limit is likely to be reached before the 2059cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches are full. This means the worst case sizing of the combined 2060cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * sizes of the caches is unlikely to ever be necessary. However, is is 2061cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * obvious read-ahead up to the data block cache size is always possible 2062cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * irrespective of the file open limit, because a single file could 2063cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * contain that number of blocks. 2064cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2065cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "file open limit + data block cache size" seems 2066cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * to be a reasonable estimate. We can reasonably assume the maximum 2067cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * likely read-ahead possible is data block cache size + one fragment 2068cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * per open file. 2069cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2070cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * dimensioning the to_writer queue. The size of this queue is 2071cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * directly related to the amount of block read-ahead possible. 2072cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * However, unlike the to_reader and to_deflate queues, this is 2073cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * complicated by the fact the to_writer queue not only contains 2074cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * entries for fragments and data_blocks but it also contains 2075cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * file entries, one per open file in the read-ahead. 2076cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2077cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "2 * (file open limit) + 2078cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * data block cache size" seems to be a reasonable estimate. 2079cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * We can reasonably assume the maximum likely read-ahead possible 2080cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * is data block cache size + one fragment per open file, and then 2081cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * we will have a file_entry for each open file. 2082cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2083cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher res = getrlimit(RLIMIT_NOFILE, &rlim); 2084cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (res == -1) { 2085cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher ERROR("failed to get open file limit! Defaulting to 1\n"); 2086cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher rlim.rlim_cur = 1; 2087cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2088cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2089cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur != RLIM_INFINITY) { 2090cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2091cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * leave OPEN_FILE_MARGIN free (rlim_cur includes fds used by 2092cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * stdin, stdout, stderr and filesystem fd 2093cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2094cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur <= OPEN_FILE_MARGIN) 2095cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* no margin, use minimum possible */ 2096cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = 1; 2097cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher else 2098cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = rlim.rlim_cur - OPEN_FILE_MARGIN; 2099cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else 2100cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = -1; 2101cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2102cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* set amount of available files for use by open_wait and close_wake */ 2103cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_init(max_files); 2104cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2105cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2106cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * allocate to_reader, to_deflate and to_writer queues. Set based on 2107cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * open file limit and cache size, unless open file limit is unlimited, 2108cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * in which case set purely based on cache limits 21092b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 21102b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not overflow 21112b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * a signed int 2112cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2113cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (max_files != -1) { 21142b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(data_buffer_size, max_files) || 21152b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher add_overflow(data_buffer_size, max_files * 2)) 21162b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 21172b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2118cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(max_files + data_buffer_size); 2119cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_deflate = queue_init(max_files + data_buffer_size); 2120cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(max_files * 2 + data_buffer_size); 2121cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else { 21222b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher int all_buffers_size; 21232b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 21242b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(fragment_buffer_size, data_buffer_size)) 21252b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 21262b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 21272b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 21282b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher all_buffers_size = fragment_buffer_size + data_buffer_size; 21292b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 21302b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(all_buffers_size, all_buffers_size)) 21312b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 21322b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 2133cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2134cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(all_buffers_size); 2135cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_deflate = queue_init(all_buffers_size); 2136cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(all_buffers_size * 2); 2137cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2138cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 21398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 2140cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 21418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 21428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 21438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 21448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 2145eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 21468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 21478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 2149c435240f52b78b0ef498118727ba8dad186db26bplougher if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 2150c435240f52b78b0ef498118727ba8dad186db26bplougher 0) 21518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 21528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 21538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 21558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 21568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) 2158c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" 2159c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 21608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 21618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21631b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 21641b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 21651b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 21661b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = TRUE; 21671b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 21681b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 21691b42101056befe25b5f19d5b099e806a2ecee9cdplougher 21701b42101056befe25b5f19d5b099e806a2ecee9cdplougher 21711b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 21721b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 21731b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 21741b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 21751b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 21761b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 21771b42101056befe25b5f19d5b099e806a2ecee9cdplougher 21781b42101056befe25b5f19d5b099e806a2ecee9cdplougher 2179eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar() 2180eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 21811b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2182eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_signal(&progress_wait); 21831b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 2184eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2185eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2186eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2187eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 2188eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2189eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 2190b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher int max_digits, used, hashes, spaces; 2191dce832998340bea4236fddb5ba1525121044ce18plougher static int tty = -1; 2192eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2193b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher if(max == 0) 2194b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher return; 2195b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2196b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher max_digits = floor(log10(max)) + 1; 2197b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher used = max_digits * 2 + 11; 2198b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher hashes = (current * (columns - used)) / max; 2199b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher spaces = columns - used - hashes; 2200b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2201eaf639366792995c36ae7295bddf534f6f416643plougher if((current > max) || (columns - used < 0)) 2202eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 2203eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2204dce832998340bea4236fddb5ba1525121044ce18plougher if(tty == -1) 2205dce832998340bea4236fddb5ba1525121044ce18plougher tty = isatty(STDOUT_FILENO); 2206dce832998340bea4236fddb5ba1525121044ce18plougher if(!tty) { 2207dce832998340bea4236fddb5ba1525121044ce18plougher static long long previous = -1; 2208dce832998340bea4236fddb5ba1525121044ce18plougher 22090a0d045642e8e413f90b770539193d3fd1522786plougher /* 22100a0d045642e8e413f90b770539193d3fd1522786plougher * Updating much more frequently than this results in huge 22110a0d045642e8e413f90b770539193d3fd1522786plougher * log files. 22120a0d045642e8e413f90b770539193d3fd1522786plougher */ 2213dce832998340bea4236fddb5ba1525121044ce18plougher if((current % 100) != 0 && current != max) 2214dce832998340bea4236fddb5ba1525121044ce18plougher return; 2215dce832998340bea4236fddb5ba1525121044ce18plougher /* Don't update just to rotate the spinner. */ 2216dce832998340bea4236fddb5ba1525121044ce18plougher if(current == previous) 2217dce832998340bea4236fddb5ba1525121044ce18plougher return; 2218dce832998340bea4236fddb5ba1525121044ce18plougher previous = current; 2219dce832998340bea4236fddb5ba1525121044ce18plougher } 2220dce832998340bea4236fddb5ba1525121044ce18plougher 2221eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 2222eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2223eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 2224eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 2225eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2226eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 2227eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2228eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 2229eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 2230eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2231eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 2232eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 2233eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 2234eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2235eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2236eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 22372b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint parse_number(char *arg, int *res) 22382b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 22392b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher char *b; 22402b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher long number = strtol(arg, &b, 10); 22412b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22422b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check for trailing junk after number */ 22432b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(*b != '\0') 22442b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 22452b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22467f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher /* 22477f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * check for strtol underflow or overflow in conversion. 22487f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * Note: strtol can validly return LONG_MIN and LONG_MAX 22497f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * if the user entered these values, but, additional code 22507f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * to distinguish this scenario is unnecessary, because for 22517f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * our purposes LONG_MIN and LONG_MAX are too large anyway 22527f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher */ 22532b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number == LONG_MIN || number == LONG_MAX) 22542b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 22552b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22562b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* reject negative numbers as invalid */ 22572b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number < 0) 22582b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 22592b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22602b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check if long result will overflow signed int */ 22612b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number > INT_MAX) 22622b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 22632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher *res = number; 22652b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 1; 22662b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 22672b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 22682b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2269443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 227009b269ae68dcc1ce96b8d17cf8a09a2b0dfcbf2aPhillip Lougher printf("unsquashfs version 4.2-git (2012/12/21)\n");\ 22710ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher printf("copyright (C) 2012 Phillip Lougher "\ 227283d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher "<phillip@squashfs.org.uk>\n\n");\ 2273e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is free software; you can redistribute it and/or"\ 2274d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2275e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("modify it under the terms of the GNU General Public License"\ 2276d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2277e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("as published by the Free Software Foundation; either version "\ 2278e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "2,\n");\ 2279e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("or (at your option) any later version.\n\n");\ 2280e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is distributed in the hope that it will be "\ 2281e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "useful,\n");\ 2282d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ 2283d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2284d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ 2285d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2286443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 2287443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 2288443c15812032991c98b33b5424b17bcd55fe3575plougher{ 2289443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 2290b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 2291545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 2292a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 2293a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 2294ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 2295ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 2296443c15812032991c98b33b5424b17bcd55fe3575plougher 22971b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 2298545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 2299545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 23009dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 23019dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 2302443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 2303443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 2304443c15812032991c98b33b5424b17bcd55fe3575plougher break; 2305d4204758f77acb5a371fa1487a755b76a05d5476plougher if(strcmp(argv[i], "-version") == 0 || 2306d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-v") == 0) { 2307443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 2308443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 2309d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-info") == 0 || 2310d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-i") == 0) 2311443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 2312c435240f52b78b0ef498118727ba8dad186db26bplougher else if(strcmp(argv[i], "-ls") == 0 || 2313c435240f52b78b0ef498118727ba8dad186db26bplougher strcmp(argv[i], "-l") == 0) 2314443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 2315d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-no-progress") == 0 || 2316d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-n") == 0) 2317296d7d8a68e33341d68f4354b5e1fe2f3aa275a6plougher progress = FALSE; 231831638061a6de0cb89093672aa71ddeb42f2eb28aplougher else if(strcmp(argv[i], "-no-xattrs") == 0 || 231931638061a6de0cb89093672aa71ddeb42f2eb28aplougher strcmp(argv[i], "-no") == 0) 232031638061a6de0cb89093672aa71ddeb42f2eb28aplougher no_xattrs = TRUE; 2321df9d38a515489c2c573754ad81abd230dfd8b1f0plougher else if(strcmp(argv[i], "-xattrs") == 0 || 2322df9d38a515489c2c573754ad81abd230dfd8b1f0plougher strcmp(argv[i], "-x") == 0) 2323df9d38a515489c2c573754ad81abd230dfd8b1f0plougher no_xattrs = FALSE; 2324d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-dest") == 0 || 2325d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-d") == 0) { 232671add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2327d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -dest missing filename\n", 2328d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 232971add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 233071add234b27054974d5e29f95b3fab3072792a62plougher } 2331443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 2332d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-processors") == 0 || 2333d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-p") == 0) { 2334c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 23352c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher !parse_number(argv[i], 23362c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher &processors)) { 2337d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors missing or invalid " 2338d4204758f77acb5a371fa1487a755b76a05d5476plougher "processor number\n", argv[0]); 23390cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 23400cf5c297bec42c7c220d2825f12f9499f2293279plougher } 23410cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 2342d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors should be 1 or larger\n", 2343d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 23440cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 23450cf5c297bec42c7c220d2825f12f9499f2293279plougher } 2346d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-data-queue") == 0 || 2347d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-da") == 0) { 2348c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 23492b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 23502b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &data_buffer_size)) { 2351c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -data-queue missing or invalid " 2352c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2353ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2354ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2355ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 2356d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue should be 1 Mbyte or " 2357d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2358ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2359ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2360d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || 2361d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-fr") == 0) { 2362c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 23632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 23642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &fragment_buffer_size)) { 2365c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -frag-queue missing or invalid " 2366c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2367ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2368ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2369ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 2370d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue should be 1 Mbyte or " 2371d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2372ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2373ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2374d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-force") == 0 || 2375d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-f") == 0) 2376a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 2377d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-stat") == 0 || 2378d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-s") == 0) 2379b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 2380d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-lls") == 0 || 2381d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-ll") == 0) { 23829baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 23839baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2384d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-linfo") == 0 || 2385d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-li") == 0) { 23869baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 23879baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2388d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-ef") == 0 || 2389d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-e") == 0) { 239071add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2391d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -ef missing filename\n", 2392d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 239371add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 239471add234b27054974d5e29f95b3fab3072792a62plougher } 2395a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 2396d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-regex") == 0 || 2397d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-r") == 0) 23984dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 23994dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2400b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2401443c15812032991c98b33b5424b17bcd55fe3575plougher } 2402443c15812032991c98b33b5424b17bcd55fe3575plougher 2403feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher if(lsonly || info) 2404feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher progress = FALSE; 2405feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher 2406bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#ifdef SQUASHFS_TRACE 2407bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher progress = FALSE; 2408bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#endif 2409bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher 2410443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2411443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2412443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 2413d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("SYNTAX: %s [options] filesystem [directories or " 2414d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract]\n", argv[0]); 2415d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-v[ersion]\t\tprint version, licence and " 2416d4204758f77acb5a371fa1487a755b76a05d5476plougher "copyright information\n"); 2417d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " 2418d4204758f77acb5a371fa1487a755b76a05d5476plougher "default \"squashfs-root\"\n"); 2419c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-n[o-progress]\t\tdon't display the progress " 2420c435240f52b78b0ef498118727ba8dad186db26bplougher "bar\n"); 2421df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" 2422df9d38a515489c2c573754ad81abd230dfd8b1f0plougher NOXOPT_STR"\n"); 2423df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-x[attrs]\t\textract xattrs in file system" 2424df9d38a515489c2c573754ad81abd230dfd8b1f0plougher XOPT_STR "\n"); 2425c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-p[rocessors] <number>\tuse <number> " 2426c435240f52b78b0ef498118727ba8dad186db26bplougher "processors. By default will use\n"); 2427c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tnumber of processors available\n"); 2428c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-i[nfo]\t\t\tprint files as they are " 2429c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed\n"); 2430c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-li[nfo]\t\tprint files as they are " 2431c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed with file\n"); 2432c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tattributes (like ls -l output)\n"); 2433d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" 2434d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2435c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-ll[s]\t\t\tlist filesystem with file " 2436c435240f52b78b0ef498118727ba8dad186db26bplougher "attributes (like\n"); 2437c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tls -l output), but don't unsquash\n"); 2438c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-f[orce]\t\tif file already exists then " 2439c435240f52b78b0ef498118727ba8dad186db26bplougher "overwrite\n"); 2440d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " 2441d4204758f77acb5a371fa1487a755b76a05d5476plougher "information\n"); 2442d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-e[f] <extract file>\tlist of directories or " 2443d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract.\n\t\t\t\tOne per line\n"); 2444c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-da[ta-queue] <size>\tSet data queue to " 2445c435240f52b78b0ef498118727ba8dad186db26bplougher "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", 2446d4204758f77acb5a371fa1487a755b76a05d5476plougher DATA_BUFFER_DEFAULT); 24478bc376ba1f7110fb88989e5134b74aa8412fb00eplougher ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " 2448d56f6723626a391b473c2c023b628abcd8ed31e3Phillip Lougher "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", 2449d4204758f77acb5a371fa1487a755b76a05d5476plougher FRAGMENT_BUFFER_DEFAULT); 2450c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX " 2451c435240f52b78b0ef498118727ba8dad186db26bplougher "regular expressions\n"); 2452c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\trather than use the default shell " 2453c435240f52b78b0ef498118727ba8dad186db26bplougher "wildcard\n\t\t\t\texpansion (globbing)\n"); 2454076b053e2cce5c9172b4f385e866c2e606712a32plougher ERROR("\nDecompressors available:\n"); 2455076b053e2cce5c9172b4f385e866c2e606712a32plougher display_compressors("", ""); 2456443c15812032991c98b33b5424b17bcd55fe3575plougher } 2457443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2458443c15812032991c98b33b5424b17bcd55fe3575plougher } 2459443c15812032991c98b33b5424b17bcd55fe3575plougher 246071add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2461a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2462b54566f5c433764830c29c83151691d0034de094plougher 2463443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2464d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Could not open %s, because %s\n", argv[i], 2465d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 2466443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2467443c15812032991c98b33b5424b17bcd55fe3575plougher } 2468443c15812032991c98b33b5424b17bcd55fe3575plougher 246902bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2470443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2471443c15812032991c98b33b5424b17bcd55fe3575plougher 2472b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2473b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2474b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2475b624936abba03d38b7e9245c647339d8f6f34274plougher } 2476b624936abba03d38b7e9245c647339d8f6f34274plougher 2477f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher if(!comp->supported) { 2478f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Filesystem uses %s compression, this is " 2479f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher "unsupported by this version\n", comp->name); 2480f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher ERROR("Decompressors available:\n"); 2481f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher display_compressors("", ""); 2482f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher exit(1); 2483f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher } 2484f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher 248527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_size = sBlk.s.block_size; 248627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_log = sBlk.s.block_log; 2487ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2488009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher /* 24892b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Sanity check block size and block log. 24902b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 24912b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check they're within correct limits 24922b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 24932b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size > SQUASHFS_FILE_MAX_SIZE || 24942b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher block_log > SQUASHFS_FILE_MAX_LOG) 24952b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size or block_log too large." 24962b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 24972b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24982b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 24992b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check block_size and block_log match 25002b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 25012b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size != (1 << block_log)) 25022b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size and block_log do not match." 25032b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 25042b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25052b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 2506009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * convert from queue size in Mbytes to queue size in 25072b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * blocks. 25082b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 25092b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not 25102b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * overflow a signed int 2511009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher */ 25122b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(fragment_buffer_size, 20 - block_log)) 25132b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Fragment queue size is too large\n"); 25142b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 25152b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher fragment_buffer_size <<= 20 - block_log; 25162b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25172b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(data_buffer_size, 20 - block_log)) 25182b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 25192b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 25202b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher data_buffer_size <<= 20 - block_log; 25212b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 25228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 25238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 252444a6967088416c9bd6ee7165bde59c9ba5ccb704plougher fragment_data = malloc(block_size); 252544a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(fragment_data == NULL) 2526443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2527443c15812032991c98b33b5424b17bcd55fe3575plougher 252844a6967088416c9bd6ee7165bde59c9ba5ccb704plougher file_data = malloc(block_size); 252944a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(file_data == NULL) 2530443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2531443c15812032991c98b33b5424b17bcd55fe3575plougher 253244a6967088416c9bd6ee7165bde59c9ba5ccb704plougher data = malloc(block_size); 253344a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(data == NULL) 2534eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2535443c15812032991c98b33b5424b17bcd55fe3575plougher 253644a6967088416c9bd6ee7165bde59c9ba5ccb704plougher created_inode = malloc(sBlk.s.inodes * sizeof(char *)); 253744a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(created_inode == NULL) 2538443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2539443c15812032991c98b33b5424b17bcd55fe3575plougher 254027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 2541443c15812032991c98b33b5424b17bcd55fe3575plougher 25421a7e7e871169a6cb6e3470a50b33db83830886e2plougher if(s_ops.read_uids_guids() == FALSE) 25431a7e7e871169a6cb6e3470a50b33db83830886e2plougher EXIT_UNSQUASH("failed to uid/gid table\n"); 2544ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2545cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher if(s_ops.read_fragment_table() == FALSE) 2546cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher EXIT_UNSQUASH("failed to read fragment table\n"); 2547ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 254827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher uncompress_inode_table(sBlk.s.inode_table_start, 254927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 2550ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 255127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher uncompress_directory_table(sBlk.s.directory_table_start, 255227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start); 2553443c15812032991c98b33b5424b17bcd55fe3575plougher 255431638061a6de0cb89093672aa71ddeb42f2eb28aplougher if(no_xattrs) 255531638061a6de0cb89093672aa71ddeb42f2eb28aplougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 255631638061a6de0cb89093672aa71ddeb42f2eb28aplougher 25578935dc25479321709c74c2f8214cf5365669100eplougher if(read_xattrs_from_disk(fd, &sBlk.s) == 0) 25588935dc25479321709c74c2f8214cf5365669100eplougher EXIT_UNSQUASH("failed to read the xattr table\n"); 25598935dc25479321709c74c2f8214cf5365669100eplougher 2560a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2561a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2562a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2563a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2564a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 256527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 256627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2567eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 256827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 25699b58176e667b67770569c9076a410b27aaa3bcf5plougher inode_number = 1; 2570eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2571c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%d inodes (%d blocks) to write\n\n", total_inodes, 2572c435240f52b78b0ef498118727ba8dad186db26bplougher total_inodes - total_files + total_blocks); 2573eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 25741b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 25751b42101056befe25b5f19d5b099e806a2ecee9cdplougher enable_progress_bar(); 25761b42101056befe25b5f19d5b099e806a2ecee9cdplougher 257727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 257827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2579443c15812032991c98b33b5424b17bcd55fe3575plougher 25808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 25818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 25828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 25835c7885bc293ab675812fd77a05f59c2917e3e8b4plougher if(progress) { 25841b42101056befe25b5f19d5b099e806a2ecee9cdplougher disable_progress_bar(); 25855c7885bc293ab675812fd77a05f59c2917e3e8b4plougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 25861b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_inodes - total_files + total_blocks, columns); 25875c7885bc293ab675812fd77a05f59c2917e3e8b4plougher } 2588eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2589443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2590443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2591443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2592443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2593443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2594443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2595443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2596443c15812032991c98b33b5424b17bcd55fe3575plougher } 2597eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 25989dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2599443c15812032991c98b33b5424b17bcd55fe3575plougher} 2600