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, 6cc06495ccafaf9bb7f3d078dee22f2e3b1af471cPhillip Lougher * 2012, 2013, 2014 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" 29efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher#include "compressor.h" 302ef25cb004cc6995bd36f781863aa844fe8c358dplougher#include "xattr.h" 31fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher#include "unsquashfs_info.h" 320100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher#include "stdarg.h" 338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 34cdebd2b8ae4b1ac39eefb5f0c556f0d2e3dc3d24plougher#include <sys/sysinfo.h> 352ef25cb004cc6995bd36f781863aa844fe8c358dplougher#include <sys/types.h> 36cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#include <sys/time.h> 37cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#include <sys/resource.h> 382b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher#include <limits.h> 39e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher#include <ctype.h> 40cdebd2b8ae4b1ac39eefb5f0c556f0d2e3dc3d24plougher 418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *fragment_cache, *data_cache; 42bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougherstruct queue *to_reader, *to_inflate, *to_writer, *from_writer; 433327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougherpthread_t *thread, *inflator_thread; 448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_mutex_t fragment_mutex; 458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* user options that control parallelisation */ 478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint processors = -1; 488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 496490378e5b5e8dc058daf28423a7465699a6ba7bplougherstruct super_block sBlk; 5002bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_operations s_ops; 51efda88fd6fbb19543a86b5f8d15b437bba8c4674plougherstruct compressor *comp; 5202bc3bcabf2b219f63961f07293b83629948f026plougher 539dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, 549dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher dev_count = 0, fifo_count = 0; 55443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 56443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 57443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 58443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 59443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 60443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 61443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 62443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 63443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 64ae271cc93e3684d5314bcdc45b631e497ae43166plougherunsigned int block_log; 65d4204758f77acb5a371fa1487a755b76a05d5476plougherint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; 66d4204758f77acb5a371fa1487a755b76a05d5476plougherint use_regex = FALSE; 67443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 689dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint root_process; 69eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint columns; 70eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint rotate = 0; 711b42101056befe25b5f19d5b099e806a2ecee9cdplougherpthread_mutex_t screen_mutex; 721b42101056befe25b5f19d5b099e806a2ecee9cdplougherint progress = TRUE, progress_enabled = FALSE; 73eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int total_blocks = 0, total_files = 0, total_inodes = 0; 74eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int cur_blocks = 0; 75ed5124f016834932db2c63d60d259d846171c216plougherint inode_number = 1; 76df9d38a515489c2c573754ad81abd230dfd8b1f0plougherint no_xattrs = XATTR_DEF; 77498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougherint user_xattrs = FALSE; 78443c15812032991c98b33b5424b17bcd55fe3575plougher 79476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 80476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 81476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 82476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 83476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 84476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 85476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 86476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 87476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 88476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 89eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFREG, 90eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFLNK, 91eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFBLK, 92eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFCHR, 93eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFIFO, 94eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFSOCK 95476dcb48b24efff22caa970f000e151f1b28918dplougher}; 96476dcb48b24efff22caa970f000e151f1b28918dplougher 97476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 98476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 99476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 100476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 101476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 102476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 103476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 104476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 105476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 106476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 107476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 108476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 109476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 110476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 111476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 112476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 113476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 114476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 115476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 116476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 117476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 118476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 1198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 1208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 124afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher#define MAX_LINE 16384 125afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher 1260100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Loughervoid prep_exit() 1270100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher{ 1280100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher} 1290100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 1300100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 131eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 132eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 133eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 134eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 135eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 136c27a3d72b339d80d38623a4ee5a42601338fb4c9plougher if(isatty(STDOUT_FILENO)) 137d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 138d4204758f77acb5a371fa1487a755b76a05d5476plougher "columns\n"); 139eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 140eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 141eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 142eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 143eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1451b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 1461b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 1471b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 1481b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 1491b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1501b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1512b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint add_overflow(int a, int b) 1522b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1532b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX - a) < b; 1542b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1552b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1562b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1572b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint shift_overflow(int a, int shift) 1582b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1592b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX >> shift) < a; 1602b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1612b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1622b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint multiply_overflow(int a, int multiplier) 1642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 1652b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return (INT_MAX / multiplier) < a; 1662b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 1672b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1682b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 1708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 1728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 17462b2d7649ad84234afd928a43f9a2c1612eef361plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1762b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(size, 1) || 1772b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher multiply_overflow(size + 1, sizeof(void *))) 1782b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Size too large in queue_init\n"); 1792b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 1807b53be8c83b949517c343d9c6d88243578753c3aplougher queue->data = malloc(sizeof(void *) * (size + 1)); 1817b53be8c83b949517c343d9c6d88243578753c3aplougher if(queue->data == NULL) 1820e0cc6f6dccdc5460c292b0a5accc1184a07f3f5plougher EXIT_UNSQUASH("Out of memory in queue_init\n"); 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 1868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 1878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 1888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 1898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 1918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1948888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 1958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 1978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 2018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 2028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 2048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 2058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 2068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2108888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 2118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 2138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 2148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 2168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 2178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 2198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 2208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 2218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 2228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 2248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 227acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Loughervoid dump_queue(struct queue *queue) 228acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher{ 229acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher pthread_mutex_lock(&queue->mutex); 230acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher 231acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher printf("Max size %d, size %d%s\n", queue->size - 1, 232acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher queue->readp <= queue->writep ? queue->writep - queue->readp : 233acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher queue->size - queue->readp + queue->writep, 234acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher queue->readp == queue->writep ? " (EMPTY)" : 235acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher ((queue->writep + 1) % queue->size) == queue->readp ? 236acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher " (FULL)" : ""); 237acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher 238acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher pthread_mutex_unlock(&queue->mutex); 239acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher} 240acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher 241acabfdbb5244ddc04c2d372e20b79fccdafb5cbePhillip Lougher 2428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2438888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 2448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 2468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 2488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 2528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2568888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 2578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 2598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 2608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 261c435240f52b78b0ef498118727ba8dad186db26bplougher cache->hash_table[CALCULATE_HASH(entry->block)] = 262c435240f52b78b0ef498118727ba8dad186db26bplougher entry->hash_next; 2638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 2658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 2678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2718888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 2728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 2748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 2758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 2768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 2778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 2788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2868888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 2878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 28856b6f5f361fe521ce75a7c189724a84987cd3d13Phillip Lougher if(entry->free_prev == NULL || entry->free_next == NULL) 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 2908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 291222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 2928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 2988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 2998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 3008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 3078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 3088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 3098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 311360570574b8f7786728d91d5fe4a0a4aa291fa03plougher EXIT_UNSQUASH("Out of memory in cache_init\n"); 3128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 3148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 3158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 3166b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher cache->used = 0; 3178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 3188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 3218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 3228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 3238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 3248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 3308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 331d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 332d4204758f77acb5a371fa1487a755b76a05d5476plougher * Get a block out of the cache. If the block isn't in the cache 3333327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougher * it is added and queued to the reader() and inflate() threads for 334c435240f52b78b0ef498118727ba8dad186db26bplougher * reading off disk and decompression. The cache grows until max_blocks 335c435240f52b78b0ef498118727ba8dad186db26bplougher * is reached, once this occurs existing discarded blocks on the free 336c435240f52b78b0ef498118727ba8dad186db26bplougher * list are reused 337d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 3398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 3408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 3448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 3458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 3468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 348d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 349b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher * found the block in the cache. If the block is currently unused 350b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher * remove it from the free list and increment cache used count. 3518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 352b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher if(entry->used == 0) { 353b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher cache->used ++; 354b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher remove_free_list(cache, entry); 355b55ce2730ff8cda018d8d18e64c9cbda433593afPhillip Lougher } 3568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 3578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 359d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 360d4204758f77acb5a371fa1487a755b76a05d5476plougher * not in the cache 361d4204758f77acb5a371fa1487a755b76a05d5476plougher * 362d4204758f77acb5a371fa1487a755b76a05d5476plougher * first try to allocate new block 363d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 3658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 3668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 3677227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 3697227416360c2f249a0783dffef6725ad03b61c99plougher if(entry->data == NULL) 3707227416360c2f249a0783dffef6725ad03b61c99plougher EXIT_UNSQUASH("Out of memory in cache_get\n"); 3718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 3728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 3748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 375d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 376d4204758f77acb5a371fa1487a755b76a05d5476plougher * try to get from free list 377d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 380d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&cache->wait_for_free, 381d4204758f77acb5a371fa1487a755b76a05d5476plougher &cache->mutex); 3828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 3848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 3868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 388d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 3896b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher * Initialise block and insert into the hash table. 3906b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher * Increment used which tracks how many buffers in the 3916b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher * cache are actively in use (the other blocks, count - used, 3926b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher * are in the cache and available for lookup, but can also be 3936b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher * re-used). 394d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 3988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 3998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 4008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 4016b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher cache->used ++; 4028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 403d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 404c435240f52b78b0ef498118727ba8dad186db26bplougher * queue to read thread to read and ultimately (via the 405c435240f52b78b0ef498118727ba8dad186db26bplougher * decompress threads) decompress the buffer 4068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 4078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 4088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 4128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4158888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 4168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 417d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 418d4204758f77acb5a371fa1487a755b76a05d5476plougher * mark cache entry as being complete, reading and (if necessary) 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 421d4204758f77acb5a371fa1487a755b76a05d5476plougher * becomes ready but with an error... 422d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 4258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 4268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 427d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 428c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_pending flag is set, one or more threads may be waiting 429c435240f52b78b0ef498118727ba8dad186db26bplougher * on this buffer 430d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 4328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 4338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 4348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4408888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 4418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 442d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 443d4204758f77acb5a371fa1487a755b76a05d5476plougher * wait for this cache entry to become ready, when reading and (if 444d4204758f77acb5a371fa1487a755b76a05d5476plougher * necessary) decompression has taken place 445d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 4498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 450d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&entry->cache->wait_for_pending, 451d4204758f77acb5a371fa1487a755b76a05d5476plougher &entry->cache->mutex); 4528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 4568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4588888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 4598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 460d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 461d4204758f77acb5a371fa1487a755b76a05d5476plougher * finished with this cache entry, once the usage count reaches zero it 462c435240f52b78b0ef498118727ba8dad186db26bplougher * can be reused and is put onto the free list. As it remains 463c435240f52b78b0ef498118727ba8dad186db26bplougher * accessible via the hash table it can be found getting a new lease of 464c435240f52b78b0ef498118727ba8dad186db26bplougher * life before it is reused. 465d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 4698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 4708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 4716b336d83d3546674593f7de3be86d174f32fd753Phillip Lougher entry->cache->used --; 4728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 473d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 474c435240f52b78b0ef498118727ba8dad186db26bplougher * if the wait_free flag is set, one or more threads may be 475c435240f52b78b0ef498118727ba8dad186db26bplougher * waiting on this buffer 476d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 4788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 4798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 4808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 485476dcb48b24efff22caa970f000e151f1b28918dplougher 486476dcb48b24efff22caa970f000e151f1b28918dplougher 487cece843c2aff7b4775b60b04f24822f477b7b488Phillip Loughervoid dump_cache(struct cache *cache) 488cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher{ 489cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher pthread_mutex_lock(&cache->mutex); 490cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher 491cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher printf("Max buffers %d, Current size %d, Used %d, %s\n", 492cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher cache->max_buffers, cache->count, cache->used, 493cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher cache->free_list ? "Free buffers" : "No free buffers"); 494cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher 495cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher pthread_mutex_unlock(&cache->mutex); 496cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher} 497cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher 498cece843c2aff7b4775b60b04f24822f477b7b488Phillip Lougher 499476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 500476dcb48b24efff22caa970f000e151f1b28918dplougher{ 501476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 502476dcb48b24efff22caa970f000e151f1b28918dplougher 503476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 504476dcb48b24efff22caa970f000e151f1b28918dplougher 505476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 506476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 507476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 508476dcb48b24efff22caa970f000e151f1b28918dplougher } 509476dcb48b24efff22caa970f000e151f1b28918dplougher 510476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 511476dcb48b24efff22caa970f000e151f1b28918dplougher} 512476dcb48b24efff22caa970f000e151f1b28918dplougher 513476dcb48b24efff22caa970f000e151f1b28918dplougher 5143edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 5156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 516476dcb48b24efff22caa970f000e151f1b28918dplougher{ 517afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char str[11], dummy[12], dummy2[12]; /* overflow safe */ 518afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher char *userstr, *groupstr; 5196f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 520476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 521476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 52288facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 523476dcb48b24efff22caa970f000e151f1b28918dplougher 524476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 525476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 526476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 527476dcb48b24efff22caa970f000e151f1b28918dplougher } 528476dcb48b24efff22caa970f000e151f1b28918dplougher 529266b83c3b162a6764407753909712fcaade951f2plougher user = getpwuid(inode->uid); 530266b83c3b162a6764407753909712fcaade951f2plougher if(user == NULL) { 531afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy, 12, "%d", inode->uid); 532afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 533afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 534afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 535afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 536afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 537afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = "*"; 538afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 539afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher userstr = dummy; 5403edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5413edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 5423edfa57b6a463f7d441d995559143f4861d62e98plougher 543266b83c3b162a6764407753909712fcaade951f2plougher group = getgrgid(inode->gid); 544266b83c3b162a6764407753909712fcaade951f2plougher if(group == NULL) { 545afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher int res = snprintf(dummy2, 12, "%d", inode->gid); 546afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher if(res < 0) 547afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher EXIT_UNSQUASH("snprintf failed in print_filename()\n"); 548afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else if(res >= 12) 549afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher /* unsigned int shouldn't ever need more than 11 bytes 550afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher * (including terminating '\0') to print in base 10 */ 551afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = "*"; 552afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher else 553afd5fec5ba90ad8efb344f814128e0d746001ea5Phillip Lougher groupstr = dummy2; 5543edfa57b6a463f7d441d995559143f4861d62e98plougher } else 5553edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 5563edfa57b6a463f7d441d995559143f4861d62e98plougher 5576f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 5583edfa57b6a463f7d441d995559143f4861d62e98plougher 5596f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 5603edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 5613edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 5623edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 5633edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 5643edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 565c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 566c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr); 5673edfa57b6a463f7d441d995559143f4861d62e98plougher 568c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%*lld ", padchars > 0 ? padchars : 0, 569c435240f52b78b0ef498118727ba8dad186db26bplougher inode->data); 5703edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5713edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 5723edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 573c435240f52b78b0ef498118727ba8dad186db26bplougher padchars = TOTALCHARS - strlen(userstr) - 574c435240f52b78b0ef498118727ba8dad186db26bplougher strlen(groupstr) - 7; 5753edfa57b6a463f7d441d995559143f4861d62e98plougher 576d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", 577c435240f52b78b0ef498118727ba8dad186db26bplougher (int) inode->data >> 8, (int) inode->data & 578c435240f52b78b0ef498118727ba8dad186db26bplougher 0xff); 5793edfa57b6a463f7d441d995559143f4861d62e98plougher break; 5803edfa57b6a463f7d441d995559143f4861d62e98plougher } 581476dcb48b24efff22caa970f000e151f1b28918dplougher 5826f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 58388facddfd83e48a907b82210ddccbb4f84d80aecplougher 584d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, 585d4204758f77acb5a371fa1487a755b76a05d5476plougher t->tm_mday, t->tm_hour, t->tm_min, pathname); 5866f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 5876f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 5883edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 5893edfa57b6a463f7d441d995559143f4861d62e98plougher 590476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 591476dcb48b24efff22caa970f000e151f1b28918dplougher} 592476dcb48b24efff22caa970f000e151f1b28918dplougher 593443c15812032991c98b33b5424b17bcd55fe3575plougher 594e3206fad5b70e7e0527db2a627ad26616a8a2429ploughervoid add_entry(struct hash_table_entry *hash_table[], long long start, 595e3206fad5b70e7e0527db2a627ad26616a8a2429plougher int bytes) 596443c15812032991c98b33b5424b17bcd55fe3575plougher{ 597443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 598443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 599443c15812032991c98b33b5424b17bcd55fe3575plougher 600cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher hash_table_entry = malloc(sizeof(struct hash_table_entry)); 601cb2cff9a58d8d92fc6edb95049469188ee49c6c9plougher if(hash_table_entry == NULL) 6024a39fa82d4614c18d2977be7898d78d20ba01a49plougher EXIT_UNSQUASH("Out of memory in add_entry\n"); 603443c15812032991c98b33b5424b17bcd55fe3575plougher 604443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 605443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 606443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 607443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 608443c15812032991c98b33b5424b17bcd55fe3575plougher} 609443c15812032991c98b33b5424b17bcd55fe3575plougher 610443c15812032991c98b33b5424b17bcd55fe3575plougher 611f404f4914fdb272a70e18664e8963d793cc90f44plougherint lookup_entry(struct hash_table_entry *hash_table[], long long start) 612443c15812032991c98b33b5424b17bcd55fe3575plougher{ 613443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 614443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 615443c15812032991c98b33b5424b17bcd55fe3575plougher 6169dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 6179dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 6187a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher 619443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 620443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 621443c15812032991c98b33b5424b17bcd55fe3575plougher 622443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 623443c15812032991c98b33b5424b17bcd55fe3575plougher} 624443c15812032991c98b33b5424b17bcd55fe3575plougher 625443c15812032991c98b33b5424b17bcd55fe3575plougher 6263306cb2b54a60a32664617118336ac141e1471b6plougherint read_fs_bytes(int fd, long long byte, int bytes, void *buff) 627443c15812032991c98b33b5424b17bcd55fe3575plougher{ 628443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 629d7f3de3408089ce187d8bc26f6072730c77628daplougher int res, count; 630443c15812032991c98b33b5424b17bcd55fe3575plougher 631c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, 632c435240f52b78b0ef498118727ba8dad186db26bplougher bytes); 633fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 634443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 6355d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 636443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 637443c15812032991c98b33b5424b17bcd55fe3575plougher } 638443c15812032991c98b33b5424b17bcd55fe3575plougher 639d7f3de3408089ce187d8bc26f6072730c77628daplougher for(count = 0; count < bytes; count += res) { 640d7f3de3408089ce187d8bc26f6072730c77628daplougher res = read(fd, buff + count, bytes - count); 641d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res < 1) { 642d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res == 0) { 643e3206fad5b70e7e0527db2a627ad26616a8a2429plougher ERROR("Read on filesystem failed because " 644e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "EOF\n"); 645d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 646d7f3de3408089ce187d8bc26f6072730c77628daplougher } else if(errno != EINTR) { 647d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because %s\n", 648d7f3de3408089ce187d8bc26f6072730c77628daplougher strerror(errno)); 649d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 650d7f3de3408089ce187d8bc26f6072730c77628daplougher } else 651d7f3de3408089ce187d8bc26f6072730c77628daplougher res = 0; 652d7f3de3408089ce187d8bc26f6072730c77628daplougher } 653443c15812032991c98b33b5424b17bcd55fe3575plougher } 654443c15812032991c98b33b5424b17bcd55fe3575plougher 655443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 656443c15812032991c98b33b5424b17bcd55fe3575plougher} 657443c15812032991c98b33b5424b17bcd55fe3575plougher 658443c15812032991c98b33b5424b17bcd55fe3575plougher 659cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougherint read_block(int fd, long long start, long long *next, int expected, 660cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher void *block) 661443c15812032991c98b33b5424b17bcd55fe3575plougher{ 662443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 663cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int offset = 2, res, compressed; 664cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int outlen = expected ? expected : SQUASHFS_METADATA_SIZE; 665443c15812032991c98b33b5424b17bcd55fe3575plougher 666443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 667923b301e304637fd5e587eb05a6f44558abae2bdplougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 668fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 669923b301e304637fd5e587eb05a6f44558abae2bdplougher c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); 670443c15812032991c98b33b5424b17bcd55fe3575plougher } else 6713306cb2b54a60a32664617118336ac141e1471b6plougher if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) 672fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 673fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 674d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, 675d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? 676d4204758f77acb5a371fa1487a755b76a05d5476plougher "compressed" : "uncompressed"); 677443c15812032991c98b33b5424b17bcd55fe3575plougher 67827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) 679443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 680443c15812032991c98b33b5424b17bcd55fe3575plougher 681cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher compressed = SQUASHFS_COMPRESSED(c_byte); 682cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 683cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 684cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher /* 685cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * The block size should not be larger than 686cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * the uncompressed size (or max uncompressed size if 687cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * expected is 0) 688cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher */ 689cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(c_byte > outlen) 690cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return 0; 691cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 692cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(compressed) { 693cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher char buffer[c_byte]; 694cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher int error; 695cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 696cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_fs_bytes(fd, start + offset, c_byte, buffer); 697cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(res == FALSE) 698fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 699443c15812032991c98b33b5424b17bcd55fe3575plougher 700b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, buffer, c_byte, 701cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher outlen, &error); 702efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 703efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 704efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 705efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 706fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 707443c15812032991c98b33b5424b17bcd55fe3575plougher } 708443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 709cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_fs_bytes(fd, start + offset, c_byte, block); 710cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(res == FALSE) 711fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 712cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = c_byte; 713443c15812032991c98b33b5424b17bcd55fe3575plougher } 714fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 715cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(next) 716cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher *next = start + offset + c_byte; 717cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 718cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher /* 719cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * if expected, then check the (uncompressed) return data 720cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher * is of the expected size 721cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher */ 722cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher if(expected && expected != res) 723cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return 0; 724cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher else 725cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher return res; 726cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher 727fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 72868ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher ERROR("read_block: failed to read block @0x%llx\n", start); 729fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 730443c15812032991c98b33b5424b17bcd55fe3575plougher} 731443c15812032991c98b33b5424b17bcd55fe3575plougher 732443c15812032991c98b33b5424b17bcd55fe3575plougher 733443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 734443c15812032991c98b33b5424b17bcd55fe3575plougher{ 735efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 736443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 737443c15812032991c98b33b5424b17bcd55fe3575plougher 738d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, 739c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : 740c435240f52b78b0ef498118727ba8dad186db26bplougher "uncompressed"); 741fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 742443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 74386561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, data) == FALSE) 74468ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 745443c15812032991c98b33b5424b17bcd55fe3575plougher 746b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, block, data, c_byte, 747b48442b2e37b3cb7efbffb032968f115eec7963cplougher block_size, &error); 748efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 749efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) { 750efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 751efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 75268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 753443c15812032991c98b33b5424b17bcd55fe3575plougher } 754443c15812032991c98b33b5424b17bcd55fe3575plougher 755efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher return res; 756443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 75786561909d9ca51a4e4ce4efcfea30b41d1d08275plougher if(read_fs_bytes(fd, start, c_byte, block) == FALSE) 75868ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 759443c15812032991c98b33b5424b17bcd55fe3575plougher 760443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 761443c15812032991c98b33b5424b17bcd55fe3575plougher } 76268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher 76368ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougherfailed: 764d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, 765c6ab26edb0c0da6b276281960d9c8748a70886feplougher c_byte); 76668ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher return FALSE; 767443c15812032991c98b33b5424b17bcd55fe3575plougher} 768443c15812032991c98b33b5424b17bcd55fe3575plougher 769443c15812032991c98b33b5424b17bcd55fe3575plougher 7701ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougherint read_inode_table(long long start, long long end) 771443c15812032991c98b33b5424b17bcd55fe3575plougher{ 772443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 773443c15812032991c98b33b5424b17bcd55fe3575plougher 7741ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher TRACE("read_inode_table: start %lld, end %lld\n", start, end); 7751ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 776443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 777c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 778c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher inode_table = realloc(inode_table, size += 779c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher SQUASHFS_METADATA_SIZE); 7801ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(inode_table == NULL) { 7811ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("Out of memory in read_inode_table"); 7821ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 7831ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher } 784c1a81ec0ca6911533aec74e690f55b7d0a7131a4plougher } 7851ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 786443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 7871ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 788cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_block(fd, start, &start, 0, inode_table + bytes); 789c435240f52b78b0ef498118727ba8dad186db26bplougher if(res == 0) { 7901ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("read_inode_table: failed to read block\n"); 7911ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 792443c15812032991c98b33b5424b17bcd55fe3575plougher } 793443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 794066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 795066439a35c69c023ca15156da81987fe5264475fPhillip Lougher /* 796066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * If this is not the last metadata block in the inode table 797066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * then it should be SQUASHFS_METADATA_SIZE in size. 798066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * Note, we can't use expected in read_block() above for this 799066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * because we don't know if this is the last block until 800066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * after reading. 801066439a35c69c023ca15156da81987fe5264475fPhillip Lougher */ 8021ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(start != end && res != SQUASHFS_METADATA_SIZE) { 8031ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher ERROR("read_inode_table: metadata block should be %d " 8041ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher "bytes in length, it is %d bytes\n", 8051ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher SQUASHFS_METADATA_SIZE, res); 806066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 8071ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher goto failed; 8081ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher } 809443c15812032991c98b33b5424b17bcd55fe3575plougher } 8101ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 8111ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher return TRUE; 8121ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher 8131ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougherfailed: 8141ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher free(inode_table); 8151ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher return FALSE; 816443c15812032991c98b33b5424b17bcd55fe3575plougher} 817443c15812032991c98b33b5424b17bcd55fe3575plougher 818443c15812032991c98b33b5424b17bcd55fe3575plougher 819d4204758f77acb5a371fa1487a755b76a05d5476plougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, 820fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher unsigned int xattr, unsigned int set_mode) 821443c15812032991c98b33b5424b17bcd55fe3575plougher{ 8226f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 823443c15812032991c98b33b5424b17bcd55fe3575plougher 8242ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, xattr); 8252ef25cb004cc6995bd36f781863aa844fe8c358dplougher 826443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 827d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to set time on %s, because %s\n", 828d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 829443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 830443c15812032991c98b33b5424b17bcd55fe3575plougher } 831443c15812032991c98b33b5424b17bcd55fe3575plougher 8329dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 8336f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 834c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("set_attributes: failed to change uid and gids " 835c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s, because %s\n", pathname, 836c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 837443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 838443c15812032991c98b33b5424b17bcd55fe3575plougher } 8399dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 8409dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 8419dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 8429dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 843d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change mode %s, because %s\n", 844d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 8459dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 846443c15812032991c98b33b5424b17bcd55fe3575plougher } 847443c15812032991c98b33b5424b17bcd55fe3575plougher 848443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 849443c15812032991c98b33b5424b17bcd55fe3575plougher} 850443c15812032991c98b33b5424b17bcd55fe3575plougher 851443c15812032991c98b33b5424b17bcd55fe3575plougher 8521c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougherint write_bytes(int fd, char *buff, int bytes) 8531c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher{ 8541c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher int res, count; 8551c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8561c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher for(count = 0; count < bytes; count += res) { 8571c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = write(fd, buff + count, bytes - count); 8581c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(res == -1) { 8591c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(errno != EINTR) { 860c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Write on output file failed because " 861c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", strerror(errno)); 8621c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return -1; 8631c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8641c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = 0; 8651c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8661c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 8671c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8681c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return 0; 8691c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher} 8701c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 8711c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 872b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 873c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherchar *zero_data = NULL; 874b9cee889506e674726856035dba52d5e1cceeb99plougher 87587f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougherint write_block(int file_fd, char *buffer, int size, long long hole, int sparse) 876b9cee889506e674726856035dba52d5e1cceeb99plougher{ 877b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 878b9cee889506e674726856035dba52d5e1cceeb99plougher 879b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 880c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse && lseek_broken == FALSE) { 881c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error = lseek(file_fd, off, SEEK_CUR); 882c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == -1) 883c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher /* failed to seek beyond end of file */ 884c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher lseek_broken = TRUE; 885c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher } 886c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 887c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if((sparse == FALSE || lseek_broken) && zero_data == NULL) { 888b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 889c435240f52b78b0ef498118727ba8dad186db26bplougher EXIT_UNSQUASH("write_block: failed to alloc " 890c435240f52b78b0ef498118727ba8dad186db26bplougher "zero data block\n"); 891b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 892b9cee889506e674726856035dba52d5e1cceeb99plougher } 893c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 894c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse == FALSE || lseek_broken) { 895b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 896b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 897b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 898d4204758f77acb5a371fa1487a755b76a05d5476plougher avail_bytes = hole > block_size ? block_size : 899d4204758f77acb5a371fa1487a755b76a05d5476plougher hole; 900d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_bytes(file_fd, zero_data, avail_bytes) 901d4204758f77acb5a371fa1487a755b76a05d5476plougher == -1) 902b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 903b9cee889506e674726856035dba52d5e1cceeb99plougher } 904b9cee889506e674726856035dba52d5e1cceeb99plougher } 905b9cee889506e674726856035dba52d5e1cceeb99plougher } 906b9cee889506e674726856035dba52d5e1cceeb99plougher 9071c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(write_bytes(file_fd, buffer, size) == -1) 908b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 909b9cee889506e674726856035dba52d5e1cceeb99plougher 910b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 911b9cee889506e674726856035dba52d5e1cceeb99plougher 912b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 913b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 914b9cee889506e674726856035dba52d5e1cceeb99plougher} 915b9cee889506e674726856035dba52d5e1cceeb99plougher 9168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 917cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; 918cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherpthread_cond_t open_empty = PTHREAD_COND_INITIALIZER; 919cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_unlimited, open_count; 920cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher#define OPEN_FILE_MARGIN 10 921cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 922cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 923cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid open_init(int count) 924cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 925cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count = count; 926cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_unlimited = count == -1; 927cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 928cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 929cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 930cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougherint open_wait(char *pathname, int flags, mode_t mode) 931cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 932cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 933cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 934cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher while (open_count == 0) 935cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_wait(&open_empty, &open_mutex); 936cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count --; 937cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 938cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 939cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 940cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher return open(pathname, flags, mode); 941cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 942cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 943cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 944cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Loughervoid close_wake(int fd) 945cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher{ 946cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close(fd); 947cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 948cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (!open_unlimited) { 949cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_lock(&open_mutex); 950cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_count ++; 951cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_cond_signal(&open_empty); 952cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher pthread_mutex_unlock(&open_mutex); 953cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 954cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher} 955cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 956cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 9572c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_file(char *pathname, int file_fd, struct inode *inode) 9582c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 9592c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 9602c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 9612c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_file: unable to malloc file\n"); 9622c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9632c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = file_fd; 9642c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->file_size = inode->data; 9652c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = inode->mode; 9662c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = inode->gid; 9672c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = inode->uid; 9682c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = inode->time; 9692c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 9702c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 9712c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->sparse = inode->sparse; 9722c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = inode->xattr; 9732c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 9742c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 9752c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9762c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9772c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Loughervoid queue_dir(char *pathname, struct dir *dir) 9782c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher{ 9792c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher struct squashfs_file *file = malloc(sizeof(struct squashfs_file)); 9802c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(file == NULL) 9812c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher EXIT_UNSQUASH("queue_dir: unable to malloc file\n"); 9822c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9832c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->fd = -1; 9842c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->mode = dir->mode; 9852c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid = dir->guid; 9862c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->uid = dir->uid; 9872c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->time = dir->mtime; 9882c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->pathname = strdup(pathname); 9892c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->xattr = dir->xattr; 9902c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_put(to_writer, file); 9912c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher} 9922c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 9932c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 99479df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 995443c15812032991c98b33b5424b17bcd55fe3575plougher{ 9968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 997f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 99879df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 99979df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 1000443c15812032991c98b33b5424b17bcd55fe3575plougher 100179df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 1002443c15812032991c98b33b5424b17bcd55fe3575plougher 1003cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher file_fd = open_wait(pathname, O_CREAT | O_WRONLY | 1004cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); 1005d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file_fd == -1) { 1006d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("write_file: failed to create file %s, because %s\n", 1007d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 1008443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1009443c15812032991c98b33b5424b17bcd55fe3575plougher } 1010443c15812032991c98b33b5424b17bcd55fe3575plougher 10116037584bc3e861ff932f5244105959c56c8560e3plougher block_list = malloc(inode->blocks * sizeof(unsigned int)); 10126037584bc3e861ff932f5244105959c56c8560e3plougher if(block_list == NULL) 10138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 1014443c15812032991c98b33b5424b17bcd55fe3575plougher 101579df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 1016443c15812032991c98b33b5424b17bcd55fe3575plougher 1017d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1018d4204758f77acb5a371fa1487a755b76a05d5476plougher * the writer thread is queued a squashfs_file structure describing the 1019009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * file. If the file has one or more blocks or a fragment they are 1020c435240f52b78b0ef498118727ba8dad186db26bplougher * queued separately (references to blocks in the cache). 1021d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 10222c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_file(pathname, file_fd, inode); 1023443c15812032991c98b33b5424b17bcd55fe3575plougher 102479df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 10258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 10268372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 10278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 10298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 10308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 1031d4204758f77acb5a371fa1487a755b76a05d5476plougher block->size = i == file_end ? inode->data & (block_size - 1) : 1032d4204758f77acb5a371fa1487a755b76a05d5476plougher block_size; 1033009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher if(block_list[i] == 0) /* sparse block */ 10348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 10358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 1036d4204758f77acb5a371fa1487a755b76a05d5476plougher block->buffer = cache_get(data_cache, start, 1037d4204758f77acb5a371fa1487a755b76a05d5476plougher block_list[i]); 10388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 1039443c15812032991c98b33b5424b17bcd55fe3575plougher } 10408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1041443c15812032991c98b33b5424b17bcd55fe3575plougher } 1042443c15812032991c98b33b5424b17bcd55fe3575plougher 104379df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 10448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 10458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 10468372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 10478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 10488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 10498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 105079df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 10518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 105279df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 105379df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 10548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 1055b9cee889506e674726856035dba52d5e1cceeb99plougher } 1056b9cee889506e674726856035dba52d5e1cceeb99plougher 1057b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 1058443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1059443c15812032991c98b33b5424b17bcd55fe3575plougher} 1060476dcb48b24efff22caa970f000e151f1b28918dplougher 1061476dcb48b24efff22caa970f000e151f1b28918dplougher 10626f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 1063443c15812032991c98b33b5424b17bcd55fe3575plougher{ 10646f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 1065443c15812032991c98b33b5424b17bcd55fe3575plougher 10666f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 1067443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 10686013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 10696013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 10706013a30bd39550decc2546a47e5168e57bfcfde8plougher 10716f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 1072c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create hardlink, " 1073c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", strerror(errno)); 1074443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1075443c15812032991c98b33b5424b17bcd55fe3575plougher } 1076443c15812032991c98b33b5424b17bcd55fe3575plougher 1077443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1078443c15812032991c98b33b5424b17bcd55fe3575plougher } 1079443c15812032991c98b33b5424b17bcd55fe3575plougher 10806f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 10816f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 10826f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 1083c435240f52b78b0ef498118727ba8dad186db26bplougher TRACE("create_inode: regular file, file_size %lld, " 1084c435240f52b78b0ef498118727ba8dad186db26bplougher "blocks %d\n", i->data, i->blocks); 1085443c15812032991c98b33b5424b17bcd55fe3575plougher 108679df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 1087443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 1088443c15812032991c98b33b5424b17bcd55fe3575plougher break; 10896f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 109099ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSYMLINK_TYPE: 1091d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: symlink, symlink_size %lld\n", 1092d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data); 1093443c15812032991c98b33b5424b17bcd55fe3575plougher 1094a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1095a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1096a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 10976f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 1098c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create symlink " 1099c435240f52b78b0ef498118727ba8dad186db26bplougher "%s, because %s\n", pathname, 1100c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1101443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1102443c15812032991c98b33b5424b17bcd55fe3575plougher } 1103443c15812032991c98b33b5424b17bcd55fe3575plougher 11042ef25cb004cc6995bd36f781863aa844fe8c358dplougher write_xattr(pathname, i->xattr); 11052ef25cb004cc6995bd36f781863aa844fe8c358dplougher 11069dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 11076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 1108c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to change " 1109c435240f52b78b0ef498118727ba8dad186db26bplougher "uid and gids on %s, because " 1110c435240f52b78b0ef498118727ba8dad186db26bplougher "%s\n", pathname, 1111c435240f52b78b0ef498118727ba8dad186db26bplougher strerror(errno)); 1112443c15812032991c98b33b5424b17bcd55fe3575plougher } 1113443c15812032991c98b33b5424b17bcd55fe3575plougher 1114443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 1115443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1116443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 111799ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_CHRDEV_TYPE: 111899ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LBLKDEV_TYPE: 111999ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LCHRDEV_TYPE: { 11206f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 1121545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 1122443c15812032991c98b33b5424b17bcd55fe3575plougher 11239dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 1124a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1125a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1126a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 11276f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 1128d4204758f77acb5a371fa1487a755b76a05d5476plougher makedev((i->data >> 8) & 0xff, 1129d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data & 0xff)) == -1) { 1130c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: failed to create " 1131c435240f52b78b0ef498118727ba8dad186db26bplougher "%s device %s, because %s\n", 1132d4204758f77acb5a371fa1487a755b76a05d5476plougher chrdev ? "character" : "block", 1133d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 1134443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1135443c15812032991c98b33b5424b17bcd55fe3575plougher } 1136c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, 1137fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->gid, i->time, i->xattr, TRUE); 1138443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 1139443c15812032991c98b33b5424b17bcd55fe3575plougher } else 1140c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("create_inode: could not create %s " 1141c435240f52b78b0ef498118727ba8dad186db26bplougher "device %s, because you're not " 1142c435240f52b78b0ef498118727ba8dad186db26bplougher "superuser!\n", chrdev ? "character" : 1143c435240f52b78b0ef498118727ba8dad186db26bplougher "block", pathname); 1144443c15812032991c98b33b5424b17bcd55fe3575plougher break; 11456f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1146443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 114799ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LFIFO_TYPE: 1148443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 1149443c15812032991c98b33b5424b17bcd55fe3575plougher 1150a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 1151a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 1152a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 1153443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 1154d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create fifo %s, " 1155d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, 1156d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 1157443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1158443c15812032991c98b33b5424b17bcd55fe3575plougher } 1159c435240f52b78b0ef498118727ba8dad186db26bplougher set_attributes(pathname, i->mode, i->uid, i->gid, 1160fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher i->time, i->xattr, TRUE); 1161443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 1162443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1163443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 116499ec5405b480bf852a0d9eed20693b750ed68943plougher case SQUASHFS_LSOCKET_TYPE: 1165443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 1166443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 1167443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1168443c15812032991c98b33b5424b17bcd55fe3575plougher default: 1169d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Unknown inode type %d in create_inode_table!\n", 1170d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type); 1171443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1172443c15812032991c98b33b5424b17bcd55fe3575plougher } 1173fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 11746f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 1175443c15812032991c98b33b5424b17bcd55fe3575plougher 1176443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1177443c15812032991c98b33b5424b17bcd55fe3575plougher} 1178443c15812032991c98b33b5424b17bcd55fe3575plougher 1179443c15812032991c98b33b5424b17bcd55fe3575plougher 1180e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougherint read_directory_table(long long start, long long end) 1181443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1182443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 1183443c15812032991c98b33b5424b17bcd55fe3575plougher 1184e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher TRACE("read_directory_table: start %lld, end %lld\n", start, end); 118541da3230b2ac91a73f9190676f66b3d80b21c270plougher 1186443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 118707d4d0dcafeb198a568f859b88034637e6e7a8e7plougher if(size - bytes < SQUASHFS_METADATA_SIZE) { 118807d4d0dcafeb198a568f859b88034637e6e7a8e7plougher directory_table = realloc(directory_table, size += 118907d4d0dcafeb198a568f859b88034637e6e7a8e7plougher SQUASHFS_METADATA_SIZE); 1190e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(directory_table == NULL) { 1191e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher ERROR("Out of memory in " 1192e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher "read_directory_table\n"); 1193e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1194e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 119507d4d0dcafeb198a568f859b88034637e6e7a8e7plougher } 1196e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1197443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 1198e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1199cf5c8b43f14bad020372fe55fb237eb2ae2b28d4Phillip Lougher res = read_block(fd, start, &start, 0, directory_table + bytes); 1200e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(res == 0) { 1201e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher ERROR("read_directory_table: failed to read block\n"); 1202e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1203e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 1204e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1205443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 1206066439a35c69c023ca15156da81987fe5264475fPhillip Lougher 1207066439a35c69c023ca15156da81987fe5264475fPhillip Lougher /* 1208066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * If this is not the last metadata block in the directory table 1209066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * then it should be SQUASHFS_METADATA_SIZE in size. 1210066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * Note, we can't use expected in read_block() above for this 1211066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * because we don't know if this is the last block until 1212066439a35c69c023ca15156da81987fe5264475fPhillip Lougher * after reading. 1213066439a35c69c023ca15156da81987fe5264475fPhillip Lougher */ 1214e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(start != end && res != SQUASHFS_METADATA_SIZE) { 121591f125a8dec54a0201423182ec523e975f93053bPhillip Lougher ERROR("read_directory_table: metadata block " 1216e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher "should be %d bytes in length, it is %d " 1217066439a35c69c023ca15156da81987fe5264475fPhillip Lougher "bytes\n", SQUASHFS_METADATA_SIZE, res); 1218e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher goto failed; 1219e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher } 1220443c15812032991c98b33b5424b17bcd55fe3575plougher } 1221e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1222e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher return TRUE; 1223e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher 1224e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougherfailed: 1225e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher free(directory_table); 1226e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher return FALSE; 1227443c15812032991c98b33b5424b17bcd55fe3575plougher} 1228443c15812032991c98b33b5424b17bcd55fe3575plougher 1229443c15812032991c98b33b5424b17bcd55fe3575plougher 12309dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 12319dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1232443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1233443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1234443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1235443c15812032991c98b33b5424b17bcd55fe3575plougher 1236443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1237443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1238443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1239443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1240443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1241443c15812032991c98b33b5424b17bcd55fe3575plougher 1242443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1243443c15812032991c98b33b5424b17bcd55fe3575plougher} 1244443c15812032991c98b33b5424b17bcd55fe3575plougher 1245443c15812032991c98b33b5424b17bcd55fe3575plougher 1246443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1247443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1248443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1249443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1250443c15812032991c98b33b5424b17bcd55fe3575plougher} 1251443c15812032991c98b33b5424b17bcd55fe3575plougher 1252443c15812032991c98b33b5424b17bcd55fe3575plougher 125304281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougherchar *get_component(char *target, char **targname) 1254b54566f5c433764830c29c83151691d0034de094plougher{ 125504281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *start; 125604281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 1257b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 12583cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1259b54566f5c433764830c29c83151691d0034de094plougher 126004281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher start = target; 12617f3c1887319ca4acff0787ed821628eb27c29f14Phillip Lougher while(*target != '/' && *target != '\0') 126204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target ++; 1263b54566f5c433764830c29c83151691d0034de094plougher 126404281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher *targname = strndup(start, target - start); 1265b54566f5c433764830c29c83151691d0034de094plougher 12667f3c1887319ca4acff0787ed821628eb27c29f14Phillip Lougher while(*target == '/') 12677f3c1887319ca4acff0787ed821628eb27c29f14Phillip Lougher target ++; 12687f3c1887319ca4acff0787ed821628eb27c29f14Phillip Lougher 1269b54566f5c433764830c29c83151691d0034de094plougher return target; 1270b54566f5c433764830c29c83151691d0034de094plougher} 1271b54566f5c433764830c29c83151691d0034de094plougher 1272b54566f5c433764830c29c83151691d0034de094plougher 12736ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 12746ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 12756ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 12766ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12776ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 12786ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 12796ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 12806ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 12816ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 12826ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 12836ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 12846ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 12856ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 12866ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12876ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 12886ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 12896ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12906ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 12914dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1292b54566f5c433764830c29c83151691d0034de094plougher{ 129304281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher char *targname; 12944dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 129571add234b27054974d5e29f95b3fab3072792a62plougher 1296b7bb000643cd21c615a0366a7365441aa9c433f2plougher TRACE("add_path: adding \"%s\" extract file\n", target); 1297b7bb000643cd21c615a0366a7365441aa9c433f2plougher 129804281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher target = get_component(target, &targname); 129971add234b27054974d5e29f95b3fab3072792a62plougher 130071add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 13019dd4507fac1c96098eda8abe699a813a59451633plougher paths = malloc(sizeof(struct pathname)); 13029dd4507fac1c96098eda8abe699a813a59451633plougher if(paths == NULL) 13034dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 13044dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 130571add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 130671add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 130771add234b27054974d5e29f95b3fab3072792a62plougher } 130871add234b27054974d5e29f95b3fab3072792a62plougher 130971add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 131071add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 131171add234b27054974d5e29f95b3fab3072792a62plougher break; 131271add234b27054974d5e29f95b3fab3072792a62plougher 13136ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 1314d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1315d4204758f77acb5a371fa1487a755b76a05d5476plougher * allocate new name entry 1316d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 131771add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 1318d4204758f77acb5a371fa1487a755b76a05d5476plougher paths->name = realloc(paths->name, (i + 1) * 1319d4204758f77acb5a371fa1487a755b76a05d5476plougher sizeof(struct path_entry)); 1320fd628227871aecb36bb2b4f9c7f664f731510cdeplougher if(paths->name == NULL) 1321fd628227871aecb36bb2b4f9c7f664f731510cdeplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 132204281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher paths->name[i].name = targname; 13236ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 13244dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 13254dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 13261f3cc42a2f77966d321a38d1709eba26f71104bdplougher if(paths->name[i].preg == NULL) 13271f3cc42a2f77966d321a38d1709eba26f71104bdplougher EXIT_UNSQUASH("Out of memory in add_path\n"); 1328d4204758f77acb5a371fa1487a755b76a05d5476plougher error = regcomp(paths->name[i].preg, targname, 1329d4204758f77acb5a371fa1487a755b76a05d5476plougher REG_EXTENDED|REG_NOSUB); 1330545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 133162859d215e7f828ace8501f5863f0c3d8b48ebf3Phillip Lougher char str[1024]; /* overflow safe */ 13324dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 13334dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 1334d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("invalid regex %s in export %s, " 1335c435240f52b78b0ef498118727ba8dad186db26bplougher "because %s\n", targname, alltarget, 1336c435240f52b78b0ef498118727ba8dad186db26bplougher str); 13374dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 13384dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 13394dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 13406ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 13416ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 1342d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1343d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component 1344d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 134571add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 134671add234b27054974d5e29f95b3fab3072792a62plougher else 1347d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1348d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1349d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13504dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 13516ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 1352d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1353d4204758f77acb5a371fa1487a755b76a05d5476plougher * existing matching entry 1354d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 135504281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher free(targname); 135604281b2f978bb7b30aa1394129ea99d2d9c47d26Phillip Lougher 13576ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 1358d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1359c435240f52b78b0ef498118727ba8dad186db26bplougher * No sub-directory which means this is the leaf 1360c435240f52b78b0ef498118727ba8dad186db26bplougher * component of a pre-existing extract which subsumes 1361c435240f52b78b0ef498118727ba8dad186db26bplougher * the extract currently being added, in which case stop 1362c435240f52b78b0ef498118727ba8dad186db26bplougher * adding components 1363d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13646ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 1365d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1366d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component and child components exist 1367c435240f52b78b0ef498118727ba8dad186db26bplougher * from more specific extracts, delete as they're 1368c435240f52b78b0ef498118727ba8dad186db26bplougher * subsumed by this extract 1369d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13706ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 13716ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 13726ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 1373d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1374d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1375d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 13766ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 137771add234b27054974d5e29f95b3fab3072792a62plougher } 137871add234b27054974d5e29f95b3fab3072792a62plougher 137971add234b27054974d5e29f95b3fab3072792a62plougher return paths; 138071add234b27054974d5e29f95b3fab3072792a62plougher} 13816ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 13826ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1383a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 138471add234b27054974d5e29f95b3fab3072792a62plougher{ 13858372232d2460411adaa2299c32a0a88665e44902plougher struct pathnames *new = malloc(sizeof(struct pathnames)); 1386c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher if(new == NULL) 1387c5671cbe8dffaff7062ceb7b75f8d96c657a67b7plougher EXIT_UNSQUASH("Out of memory in init_subdir\n"); 1388a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1389a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1390a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1391a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1392a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1393a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1394a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 13953488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths->count % PATHS_ALLOC_SIZE == 0) { 1396d4204758f77acb5a371fa1487a755b76a05d5476plougher paths = realloc(paths, sizeof(struct pathnames *) + 13973488d3bb3b89c394534ad2be909b661771a9581bplougher (paths->count + PATHS_ALLOC_SIZE) * 13983488d3bb3b89c394534ad2be909b661771a9581bplougher sizeof(struct pathname *)); 13993488d3bb3b89c394534ad2be909b661771a9581bplougher if(paths == NULL) 14003488d3bb3b89c394534ad2be909b661771a9581bplougher EXIT_UNSQUASH("Out of memory in add_subdir\n"); 14013488d3bb3b89c394534ad2be909b661771a9581bplougher } 1402a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1403a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1404a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1405a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1406a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1407a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1408a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1409a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1410a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1411a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1412a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1413a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1414a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1415a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1416a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 141771add234b27054974d5e29f95b3fab3072792a62plougher 141871add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 141971add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1420b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 142171add234b27054974d5e29f95b3fab3072792a62plougher } 142271add234b27054974d5e29f95b3fab3072792a62plougher 1423a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1424a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1425a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1426a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1427a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1428a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1429c435240f52b78b0ef498118727ba8dad186db26bplougher regexec(path->name[i].preg, name, (size_t) 0, 1430c435240f52b78b0ef498118727ba8dad186db26bplougher NULL, 0) == 0 : fnmatch(path->name[i].name, 1431c435240f52b78b0ef498118727ba8dad186db26bplougher name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 1432c435240f52b78b0ef498118727ba8dad186db26bplougher 0; 1433a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1434d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1435d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a leaf component, any subdirectories 1436c435240f52b78b0ef498118727ba8dad186db26bplougher * will implicitly match, therefore return an 1437c435240f52b78b0ef498118727ba8dad186db26bplougher * empty new search set 1438d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1439a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1440a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1441a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1442d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1443d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a non-leaf component, add any 1444c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to the new set of 1445c435240f52b78b0ef498118727ba8dad186db26bplougher * subdirectories to scan for this name 1446d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1447a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1448a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1449a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1450b54566f5c433764830c29c83151691d0034de094plougher 1451a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1452d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1453d4204758f77acb5a371fa1487a755b76a05d5476plougher * no matching names found, delete empty search set, and return 1454d4204758f77acb5a371fa1487a755b76a05d5476plougher * FALSE 1455d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1456a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1457a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1458a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1459a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1460a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1461d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 14620a0d045642e8e413f90b770539193d3fd1522786plougher * one or more matches with sub-directories found (no leaf matches), 14630a0d045642e8e413f90b770539193d3fd1522786plougher * return new search set and return TRUE 14640a0d045642e8e413f90b770539193d3fd1522786plougher */ 1465a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1466a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1467a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 1468d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1469d4204758f77acb5a371fa1487a755b76a05d5476plougher * found matching leaf exclude, return empty search set and return TRUE 1470d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1471a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1472a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1473a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1474b54566f5c433764830c29c83151691d0034de094plougher} 1475b54566f5c433764830c29c83151691d0034de094plougher 1476b54566f5c433764830c29c83151691d0034de094plougher 1477b807ab3497c01a49fed6f9daafce3bfc599a9421ploughervoid pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1478d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1479eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1480eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 1481454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *name; 1482eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 1483eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1484eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1485eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1486cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) 1487cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1488cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1489eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1490eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1491454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher char *pathname; 1492454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher int res; 1493eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1494d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", 1495d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1496eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1497eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 1498eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1499eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1500454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1501454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher if(res == -1) 1502454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1503eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1504eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 1505eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 1506eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 1507d4204758f77acb5a371fa1487a755b76a05d5476plougher if(type == SQUASHFS_FILE_TYPE || 1508d4204758f77acb5a371fa1487a755b76a05d5476plougher type == SQUASHFS_LREG_TYPE) { 1509312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 1510eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 1511d4204758f77acb5a371fa1487a755b76a05d5476plougher created_inode[i->inode_number - 1] = 1512d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) i; 1513d4204758f77acb5a371fa1487a755b76a05d5476plougher total_blocks += (i->data + 1514d4204758f77acb5a371fa1487a755b76a05d5476plougher (block_size - 1)) >> block_log; 1515eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1516eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 1517eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1518eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 1519eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1520eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1521eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 1522454c96fede0c4c424308744cbbf861df17b28f73Phillip Lougher free(pathname); 1523eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1524eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1525eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 1526eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1527eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1528eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1529a2cff53655359b044ea88baa76cb16d1c8f44d2aploughervoid dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1530d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1531443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1532443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1533d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *name; 1534a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 1535eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1536eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1537443c15812032991c98b33b5424b17bcd55fe3575plougher 1538cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher if(dir == NULL) { 1539cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher ERROR("dir_scan: failed to read directory %s, skipping\n", 1540cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher parent_name); 1541cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher return; 1542cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher } 1543cc7cea5b0d004fbaaf5e1060e6ed0fa9367e7ef0Phillip Lougher 1544eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 1545eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 1546eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 15472c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!lsonly) { 15482c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15492c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Make directory with default User rwx permissions rather than 15502c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * the permissions from the filesystem, as these may not have 15512c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * write/execute permission. These are fixed up later in 15522c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * set_attributes(). 15532c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15542c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher int res = mkdir(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 15552c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(res == -1) { 15562c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15572c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Skip directory if mkdir fails, unless we're 15582c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * forcing and the error is -EEXIST 15592c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15602c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if(!force || errno != EEXIST) { 15612c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to make directory %s, " 15622c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "because %s\n", parent_name, 15632c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher strerror(errno)); 15642c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher squashfs_closedir(dir); 15652c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher return; 15662c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 15672c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher 15682c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* 15692c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * Try to change permissions of existing directory so 15702c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher * that we can write to it 15712c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher */ 15722c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher res = chmod(parent_name, S_IRUSR|S_IWUSR|S_IXUSR); 15732c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher if (res == -1) 15742c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher ERROR("dir_scan: failed to change permissions " 15752c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher "for directory %s, because %s\n", 15762c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher parent_name, strerror(errno)); 15772c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } 157885917a285edbd4bb78f1b245f66c634d1e0d4029plougher } 1579443c15812032991c98b33b5424b17bcd55fe3575plougher 1580443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1581d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher char *pathname; 1582d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher int res; 1583d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher 1584d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", 1585d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1586b54566f5c433764830c29c83151691d0034de094plougher 158771add234b27054974d5e29f95b3fab3072792a62plougher 158871add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 1589b54566f5c433764830c29c83151691d0034de094plougher continue; 1590b54566f5c433764830c29c83151691d0034de094plougher 1591d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher res = asprintf(&pathname, "%s/%s", parent_name, name); 1592d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher if(res == -1) 1593d27d51b4bc39e050392303009e08273d9f38bdccPhillip Lougher EXIT_UNSQUASH("asprintf failed in dir_scan\n"); 1594fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1595fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher if(type == SQUASHFS_DIR_TYPE) { 159671add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 1597fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher free(pathname); 1598fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher } else if(new == NULL) { 1599fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher update_info(pathname); 1600fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher 1601312e50b7b8c9dd39577657bd3d79fcedf6e91a1bplougher i = s_ops.read_inode(start_block, offset); 16026f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 16036f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 16046f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 16056f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1606559bfb898c92e302b18b975927163eb9e49bfbd2Phillip Lougher if(!lsonly) 16076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 1608427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher 1609d4204758f77acb5a371fa1487a755b76a05d5476plougher if(i->type == SQUASHFS_SYMLINK_TYPE || 1610d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type == SQUASHFS_LSYMLINK_TYPE) 1611427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher free(i->symlink); 1612fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher } else 1613fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher free(pathname); 1614a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1615a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 1616443c15812032991c98b33b5424b17bcd55fe3575plougher } 1617443c15812032991c98b33b5424b17bcd55fe3575plougher 1618074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 16192c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher queue_dir(parent_name, dir); 1620443c15812032991c98b33b5424b17bcd55fe3575plougher 1621443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 1622443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 1623443c15812032991c98b33b5424b17bcd55fe3575plougher} 1624443c15812032991c98b33b5424b17bcd55fe3575plougher 1625443c15812032991c98b33b5424b17bcd55fe3575plougher 1626b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 1627b624936abba03d38b7e9245c647339d8f6f34274plougher{ 162827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher time_t mkfs_time = (time_t) sBlk.s.mkfs_time; 1629b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 1630b624936abba03d38b7e9245c647339d8f6f34274plougher 1631b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 1632d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 163327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "little endian " : 163427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1635b624936abba03d38b7e9245c647339d8f6f34274plougher#else 1636d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 163727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major == 4 ? "" : swap ? "big endian " : 163827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); 1639b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 1640c766500607f1ea7494b8360409be3d8ea66f9761plougher 1641d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : 1642d4204758f77acb5a371fa1487a755b76a05d5476plougher "failed to get time\n"); 1643e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", 1644e3206fad5b70e7e0527db2a627ad26616a8a2429plougher sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / 1645e3206fad5b70e7e0527db2a627ad26616a8a2429plougher (1024.0 * 1024.0)); 1646c766500607f1ea7494b8360409be3d8ea66f9761plougher 16473fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher if(sBlk.s.s_major == 4) { 1648e5e5a7502f722fae4f057f49932fe4de2501f6e8plougher printf("Compression %s\n", comp->name); 1649c766500607f1ea7494b8360409be3d8ea66f9761plougher 16503fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher if(SQUASHFS_COMP_OPTS(sBlk.s.flags)) { 1651b1b4fe22b339f73360c4e94e75ca46975c54bc06Phillip Lougher char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned)); 16523fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher int bytes; 16533fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher 16543fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher bytes = read_block(fd, sizeof(sBlk.s), NULL, 0, buffer); 16553fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher if(bytes == 0) { 16563fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher ERROR("Failed to read compressor options\n"); 16573fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher return; 16583fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher } 16593fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher 16603fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher compressor_display_options(comp, buffer, bytes); 16613fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher } 16623fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher } 16633fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher 166427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Block size %d\n", sBlk.s.block_size); 1665d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem is %sexportable via NFS\n", 166627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); 1667d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Inodes are %scompressed\n", 166827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); 1669d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Data is %scompressed\n", 167027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); 1671c766500607f1ea7494b8360409be3d8ea66f9761plougher 16727ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(sBlk.s.s_major > 1) { 16737ca09d1320cdc30a068f179b93ca5c141b55c395plougher if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) 16747ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are not stored\n"); 16757ca09d1320cdc30a068f179b93ca5c141b55c395plougher else { 16767ca09d1320cdc30a068f179b93ca5c141b55c395plougher printf("Fragments are %scompressed\n", 16777ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? 16787ca09d1320cdc30a068f179b93ca5c141b55c395plougher "un" : ""); 16799077fad8779e259fa03326b567644374e98ff171Phillip Lougher printf("Always-use-fragments option is %sspecified\n", 16807ca09d1320cdc30a068f179b93ca5c141b55c395plougher SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : 16817ca09d1320cdc30a068f179b93ca5c141b55c395plougher "not "); 16827ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 16837ca09d1320cdc30a068f179b93ca5c141b55c395plougher } 16847ca09d1320cdc30a068f179b93ca5c141b55c395plougher 1685de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(sBlk.s.s_major == 4) { 1686de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) 1687de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are not stored\n"); 1688de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher else 1689de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher printf("Xattrs are %scompressed\n", 1690de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? 1691de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher "un" : ""); 1692de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher } 1693de61cdcdf3e3edb6eb1c579ec9968c22f664c9f8plougher 1694ba95dd35ef0e9f618d926ddc1a595076adc23818plougher if(sBlk.s.s_major < 4) 1695ba95dd35ef0e9f618d926ddc1a595076adc23818plougher printf("Check data is %spresent in the filesystem\n", 1696ba95dd35ef0e9f618d926ddc1a595076adc23818plougher SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : 1697ba95dd35ef0e9f618d926ddc1a595076adc23818plougher "not "); 1698c766500607f1ea7494b8360409be3d8ea66f9761plougher 169927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 1700d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Duplicates are %sremoved\n", 170127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); 17020337de3977eec74e6a3d28e0d0863299246de8b7plougher else 17030337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 1704c766500607f1ea7494b8360409be3d8ea66f9761plougher 170527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major > 1) 170627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of fragments %d\n", sBlk.s.fragments); 1707c766500607f1ea7494b8360409be3d8ea66f9761plougher 170827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of inodes %d\n", sBlk.s.inodes); 1709c766500607f1ea7494b8360409be3d8ea66f9761plougher 171027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 4) 171127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher printf("Number of ids %d\n", sBlk.s.no_ids); 17120f74340e3b68533339adc60f418ddf59fa188f61plougher else { 17130f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of uids %d\n", sBlk.no_uids); 17140f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of gids %d\n", sBlk.no_guids); 17150f74340e3b68533339adc60f418ddf59fa188f61plougher } 1716b624936abba03d38b7e9245c647339d8f6f34274plougher 171727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); 171827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.directory_table_start 0x%llx\n", 171927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start); 1720c766500607f1ea7494b8360409be3d8ea66f9761plougher 17210ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 1) 17220ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", 17230ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.fragment_table_start); 17240ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 17250ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher if(sBlk.s.s_major > 2) 17260ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher TRACE("sBlk.s.lookup_table_start 0x%llx\n\n", 17270ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher sBlk.s.lookup_table_start); 17280ca44ca7b28597911258e0c27bd82feef73f2256Phillip Lougher 1729053da34003852e494400c1ade35b526e1821b576plougher if(sBlk.s.s_major == 4) { 173027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); 1731053da34003852e494400c1ade35b526e1821b576plougher TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", 1732053da34003852e494400c1ade35b526e1821b576plougher sBlk.s.xattr_id_table_start); 1733053da34003852e494400c1ade35b526e1821b576plougher } else { 17340f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 17350f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); 17360f74340e3b68533339adc60f418ddf59fa188f61plougher } 1737b624936abba03d38b7e9245c647339d8f6f34274plougher} 1738b624936abba03d38b7e9245c647339d8f6f34274plougher 1739b624936abba03d38b7e9245c647339d8f6f34274plougher 174059b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougherint check_compression(struct compressor *comp) 174159b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher{ 174259b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher int res, bytes = 0; 174359b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned)); 174459b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 174559b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher if(!comp->supported) { 174659b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher ERROR("Filesystem uses %s compression, this is " 174759b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher "unsupported by this version\n", comp->name); 174859b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher ERROR("Decompressors available:\n"); 174959b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher display_compressors("", ""); 175059b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher return 0; 175159b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher } 175259b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 175359b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher /* 175459b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * Read compression options from disk if present, and pass to 175559b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * the compressor to ensure we know how to decompress a filesystem 175659b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * compressed with these compression options. 175759b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * 175859b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * Note, even if there is no compression options we still call the 175959b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * compressor because some compression options may be mandatory 176059b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher * for some compressors. 176159b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher */ 176259b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher if(SQUASHFS_COMP_OPTS(sBlk.s.flags)) { 176359b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher bytes = read_block(fd, sizeof(sBlk.s), NULL, 0, buffer); 176459b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher if(bytes == 0) { 176559b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher ERROR("Failed to read compressor options\n"); 176659b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher return 0; 176759b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher } 176859b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher } 176959b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 1770b642c41261e510bc2b314008d8b01b9902554e58Phillip Lougher res = compressor_check_options(comp, sBlk.s.block_size, buffer, bytes); 177159b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 177259b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher return res != -1; 177359b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher} 177459b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 177559b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher 177602bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 1777443c15812032991c98b33b5424b17bcd55fe3575plougher{ 17786490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block_3 sBlk_3; 177964e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher struct squashfs_super_block sBlk_4; 17806490378e5b5e8dc058daf28423a7465699a6ba7bplougher 17816490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 17826490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Try to read a Squashfs 4 superblock 17836490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 178464e83fda63a1b8408ffbfa466e6c67b0de7a8c99plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), 17853306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_4); 178654660e177ba40ab08ee2f3304b9f030eb5675677plougher swap = sBlk_4.s_magic != SQUASHFS_MAGIC; 17876490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); 17886490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1789d4204758f77acb5a371fa1487a755b76a05d5476plougher if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && 1790d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk_4.s_minor == 0) { 17916490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.squashfs_opendir = squashfs_opendir_4; 17926490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment = read_fragment_4; 17936490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment_table = read_fragment_table_4; 17946490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_block_list = read_block_list_2; 17956490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_inode = read_inode_4; 17966490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_uids_guids = read_uids_guids_4; 17976490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); 1798efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 1799efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 1800efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher * Check the compression type 1801efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 180227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher comp = lookup_compressor_id(sBlk.s.compression); 18036490378e5b5e8dc058daf28423a7465699a6ba7bplougher return TRUE; 18046490378e5b5e8dc058daf28423a7465699a6ba7bplougher } 18056490378e5b5e8dc058daf28423a7465699a6ba7bplougher 18066490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 18076490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock 18086490378e5b5e8dc058daf28423a7465699a6ba7bplougher * (compatible with 1 and 2 filesystems) 18096490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 181086561909d9ca51a4e4ce4efcfea30b41d1d08275plougher read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), 18113306cb2b54a60a32664617118336ac141e1471b6plougher &sBlk_3); 1812443c15812032991c98b33b5424b17bcd55fe3575plougher 1813d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1814d4204758f77acb5a371fa1487a755b76a05d5476plougher * Check it is a SQUASHFS superblock 1815d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1816443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 181721ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic != SQUASHFS_MAGIC) { 181821ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { 18197a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher squashfs_super_block_3 sblk; 1820c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Reading a different endian SQUASHFS filesystem " 1821c435240f52b78b0ef498118727ba8dad186db26bplougher "on %s\n", source); 18226490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); 18236490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); 1824443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 1825443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 1826c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("Can't find a SQUASHFS superblock on %s\n", 1827c435240f52b78b0ef498118727ba8dad186db26bplougher source); 1828443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1829443c15812032991c98b33b5424b17bcd55fe3575plougher } 1830443c15812032991c98b33b5424b17bcd55fe3575plougher } 1831443c15812032991c98b33b5424b17bcd55fe3575plougher 183227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_magic = sBlk_3.s_magic; 183327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inodes = sBlk_3.inodes; 183427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.mkfs_time = sBlk_3.mkfs_time; 183527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size; 183627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragments = sBlk_3.fragments; 183727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_log = sBlk_3.block_log; 183827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.flags = sBlk_3.flags; 183927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_major = sBlk_3.s_major; 184027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor = sBlk_3.s_minor; 184127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.root_inode = sBlk_3.root_inode; 184227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used; 184327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start; 184427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start; 184527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; 184627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; 18476490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_uids = sBlk_3.no_uids; 18486490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_guids = sBlk_3.no_guids; 18496490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start; 18506490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start; 185127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 18526490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1853443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 185427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { 185527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.bytes_used = sBlk_3.bytes_used_2; 18566490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start_2; 18576490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start_2; 185827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; 185927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; 186002bc3bcabf2b219f63961f07293b83629948f026plougher 186127c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher if(sBlk.s.s_major == 1) { 186227c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.block_size = sBlk_3.block_size_1; 186327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = sBlk.uid_start; 1864ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1865ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 1866ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 18676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 186879e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1869ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 187027c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.fragment_table_start = 1871c435240f52b78b0ef498118727ba8dad186db26bplougher sBlk_3.fragment_table_start_2; 1872ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1873ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 1874ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 1875ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 18766f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 187779e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1878ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 187927c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher } else if(sBlk.s.s_major == 3) { 1880ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_3; 1881ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment = read_fragment_3; 1882ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment_table = read_fragment_table_3; 1883ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 1884ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_inode = read_inode_3; 188579e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 188602bc3bcabf2b219f63961f07293b83629948f026plougher } else { 188727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, 188827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher sBlk.s.s_minor); 18894c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 1890443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1891443c15812032991c98b33b5424b17bcd55fe3575plougher } 1892443c15812032991c98b33b5424b17bcd55fe3575plougher 1893efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher /* 189499c8abf4de4297b3159355a0cefe9ad6f5182827plougher * 1.x, 2.x and 3.x filesystems use gzip compression. 1895efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher */ 1896efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp = lookup_compressor("gzip"); 1897443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1898443c15812032991c98b33b5424b17bcd55fe3575plougher 1899443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 1900443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1901443c15812032991c98b33b5424b17bcd55fe3575plougher} 1902443c15812032991c98b33b5424b17bcd55fe3575plougher 1903443c15812032991c98b33b5424b17bcd55fe3575plougher 1904a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 190571add234b27054974d5e29f95b3fab3072792a62plougher{ 190671add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 1907afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher char buffer[MAX_LINE + 1]; /* overflow safe */ 1908e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher char *name; 190971add234b27054974d5e29f95b3fab3072792a62plougher 191063e21ee4b795bb900f82c18e7b5c6f7369907360plougher fd = fopen(filename, "r"); 191163e21ee4b795bb900f82c18e7b5c6f7369907360plougher if(fd == NULL) 1912e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Failed to open extract file \"%s\" because %s\n", 1913e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 1914e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1915afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher while(fgets(name = buffer, MAX_LINE + 1, fd) != NULL) { 1916e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher int len = strlen(name); 1917e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1918afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher if(len == MAX_LINE && name[len - 1] != '\n') 1919e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* line too large */ 1920e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Line too long when reading " 1921afbbfbf11bc846056666d073c94a9c8e84fcb1caPhillip Lougher "extract file \"%s\", larger than %d " 192283847c1beb852a7b3f5906a0f4c90be659e46794Phillip Lougher "bytes\n", filename, MAX_LINE); 1923e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1924e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* 1925e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * Remove '\n' terminator if it exists (the last line 1926e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * in the file may not be '\n' terminated) 1927e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1928e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(len && name[len - 1] == '\n') 1929e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name[len - 1] = '\0'; 1930e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1931e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* Skip any leading whitespace */ 1932e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher while(isspace(*name)) 1933e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1934e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1935e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if comment line, skip */ 1936e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '#') 1937e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 1938e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1939e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* check for initial backslash, to accommodate 1940e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher * filenames with leading space or leading # character 1941e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher */ 1942e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\\') 1943e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher name ++; 1944e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1945e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher /* if line is now empty after skipping characters, skip it */ 1946e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(*name == '\0') 1947e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher continue; 194871add234b27054974d5e29f95b3fab3072792a62plougher 1949a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 1950e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher } 1951e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher 1952e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher if(ferror(fd)) 1953e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher EXIT_UNSQUASH("Reading extract file \"%s\" failed because %s\n", 1954e4d5a8ee19193b451884e96b6405b6390e5b7c5ePhillip Lougher filename, strerror(errno)); 195571add234b27054974d5e29f95b3fab3072792a62plougher 195671add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 1957a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 195871add234b27054974d5e29f95b3fab3072792a62plougher} 195971add234b27054974d5e29f95b3fab3072792a62plougher 196071add234b27054974d5e29f95b3fab3072792a62plougher 1961d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1962d4204758f77acb5a371fa1487a755b76a05d5476plougher * reader thread. This thread processes read requests queued by the 1963d4204758f77acb5a371fa1487a755b76a05d5476plougher * cache_get() routine. 1964d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 19658888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 19668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 19678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 19688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 196986561909d9ca51a4e4ce4efcfea30b41d1d08275plougher int res = read_fs_bytes(fd, entry->block, 19708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 19718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 19728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 1974d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 19753327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougher * queue successfully read block to the inflate 1976c435240f52b78b0ef498118727ba8dad186db26bplougher * thread(s) for further processing 1977d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1978bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher queue_put(to_inflate, entry); 19798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1980d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1981d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has either been successfully read and is 1982d4204758f77acb5a371fa1487a755b76a05d5476plougher * uncompressed, or an error has occurred, clear pending 1983c435240f52b78b0ef498118727ba8dad186db26bplougher * flag, set error appropriately, and wake up any 1984c435240f52b78b0ef498118727ba8dad186db26bplougher * threads waiting on this buffer 1985d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 19868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 19878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 19888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 19898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1991d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1992d4204758f77acb5a371fa1487a755b76a05d5476plougher * writer thread. This processes file write requests queued by the 1993d4204758f77acb5a371fa1487a755b76a05d5476plougher * write_file() routine. 1994d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 19958888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 19968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 19978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 19988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 19998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 20008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 20018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 200287f5e0e29e5f56516daaa51b1d36cde3d86a0f1fplougher long long hole = 0; 200327636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 2004c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error; 20058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 20078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 20088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 20092c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher } else if(file->fd == -1) { 20102c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher /* write attributes for directory file->pathname */ 20112c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher set_attributes(file->pathname, file->mode, file->uid, 20122c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher file->gid, file->time, file->xattr, TRUE); 20132c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file->pathname); 20142c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher free(file); 20152c5e1385ccd9ee8e7d274331cc8a646948874538Phillip Lougher continue; 20168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 20198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 20218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2022eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 20238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 20248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 20268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 20278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 20288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 20298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 203227636cb2cec37a68313f9eb825c0548245eecad0plougher 203327636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 203427636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 203527636cb2cec37a68313f9eb825c0548245eecad0plougher 2036c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(failed) 2037c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher continue; 2038c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 2039c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher error = write_block(file_fd, block->buffer->data + 2040c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher block->offset, block->size, hole, file->sparse); 2041c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 2042c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == FALSE) { 2043d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write data block %d\n", 2044d4204758f77acb5a371fa1487a755b76a05d5476plougher i); 204527636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 20468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2047c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 20488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 20498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 20508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 20518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 205327636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 2054d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 2055d4204758f77acb5a371fa1487a755b76a05d5476plougher * corner case for hole extending to end of file 2056d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 2057d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file->sparse == FALSE || 2058d4204758f77acb5a371fa1487a755b76a05d5476plougher lseek(file_fd, hole, SEEK_CUR) == -1) { 2059d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 2060d4204758f77acb5a371fa1487a755b76a05d5476plougher * for files which we don't want to write 2061c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * sparsely, or for broken lseeks which cannot 2062c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * seek beyond end of file, write_block will do 2063c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * the right thing 2064c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher */ 20658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 2066d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_block(file_fd, "\0", 1, hole, 2067d4204758f77acb5a371fa1487a755b76a05d5476plougher file->sparse) == FALSE) { 2068d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse " 2069d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 207027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 20718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 2073d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse data " 2074d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 207527636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 20768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2079cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher close_wake(file_fd); 208027636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 2081d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(file->pathname, file->mode, file->uid, 2082fdbbd7d7e595a227e0c259fa4afc872098c9e471plougher file->gid, file->time, file->xattr, force); 208327636cb2cec37a68313f9eb825c0548245eecad0plougher else { 208427636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 208527636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 208627636cb2cec37a68313f9eb825c0548245eecad0plougher } 208779df93becb68081effabebba3006c794be308598plougher free(file->pathname); 20888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 208927636cb2cec37a68313f9eb825c0548245eecad0plougher 20908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 20918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 20928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 20938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2094d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 2095d4204758f77acb5a371fa1487a755b76a05d5476plougher * decompress thread. This decompresses buffers queued by the read thread 2096d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 20973327bd9640ed579e8022b0e3889f71c342a64193Phillip Loughervoid *inflator(void *arg) 20988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 20998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 21008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 2102bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher struct cache_entry *entry = queue_get(to_inflate); 2103efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher int error, res; 2104efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 2105b48442b2e37b3cb7efbffb032968f115eec7963cplougher res = compressor_uncompress(comp, tmp, entry->data, 2106efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, 2107efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher &error); 2108efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher 2109efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher if(res == -1) 2110efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher ERROR("%s uncompress failed with error code %d\n", 2111efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher comp->name, error); 2112efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher else 2113efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher memcpy(entry->data, tmp, res); 21148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2115d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 2116d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has been either successfully decompressed, or an error 21178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 2118d4204758f77acb5a371fa1487a755b76a05d5476plougher * wake up any threads waiting on this block 2119d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 2120efda88fd6fbb19543a86b5f8d15b437bba8c4674plougher cache_block_ready(entry, res == -1); 21218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 21228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 21238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2125eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 2126eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 21279fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher struct timespec requested_time, remaining; 21281b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 21291b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 21301b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 21311b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 213201b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher if(isatty(STDOUT_FILENO)) 213301b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 213401b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher "columns\n"); 21351b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 21361b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 21371b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 21381b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 21391b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 21401b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 21411b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 21421b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 21431b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 21441b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 21451b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 2146eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 21479fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher requested_time.tv_sec = 0; 21489fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher requested_time.tv_nsec = 250000000; 2149eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2150eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 21519fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher int res = nanosleep(&requested_time, &remaining); 21529fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher 21539fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher if(res == -1 && errno != EINTR) 21549fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher EXIT_UNSQUASH("nanosleep failed in progress thread\n"); 21559fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher 21569fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher if(progress_enabled) { 21579fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher pthread_mutex_lock(&screen_mutex); 21581b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 2159d4204758f77acb5a371fa1487a755b76a05d5476plougher fifo_count + cur_blocks, total_inodes - 2160d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks, columns); 21619fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher pthread_mutex_unlock(&screen_mutex); 21629fdf6bba5e8babda13fe13a08e3fe555bd41bfbdPhillip Lougher } 2163eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 2164eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2165eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2166eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 21678888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 21688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2169cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher struct rlimit rlim; 2170cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher int i, max_files, res; 21718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 21728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2173fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher /* block SIGQUIT and SIGHUP, these are handled by the info thread */ 21748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 21758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 2176fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher sigaddset(&sigmask, SIGHUP); 2177e0a306c5aca0aa2ca4d07593afaef79e360213a2Phillip Lougher if(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1) 21783642cef78fdbb9c4dc90cc6463443a6d005cfab2Phillip Lougher EXIT_UNSQUASH("Failed to set signal mask in initialise_threads" 2179fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher "\n"); 2180fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher 2181fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher /* 2182e0a306c5aca0aa2ca4d07593afaef79e360213a2Phillip Lougher * temporarily block these signals so the created sub-threads will 2183fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher * ignore them, ensuring the main thread handles them 2184fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher */ 2185fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher sigemptyset(&sigmask); 2186fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher sigaddset(&sigmask, SIGINT); 2187fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher sigaddset(&sigmask, SIGTERM); 2188e0a306c5aca0aa2ca4d07593afaef79e360213a2Phillip Lougher if(pthread_sigmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 21893642cef78fdbb9c4dc90cc6463443a6d005cfab2Phillip Lougher EXIT_UNSQUASH("Failed to set signal mask in initialise_threads" 2190c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 21918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 21938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 21948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 21958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 21968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 21988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 21998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 22008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 22018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 22028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 22038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 22048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 2205d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Failed to get number of available processors. " 2206d4204758f77acb5a371fa1487a755b76a05d5476plougher "Defaulting to 1\n"); 22078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 22088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 22109cc26b77a61fefdeb45f5c487c2bfdefd394b66fplougher processors = sysconf(_SC_NPROCESSORS_ONLN); 22118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 22128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 22138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 221470f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher if(add_overflow(processors, 3) || 221570f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher multiply_overflow(processors + 3, sizeof(pthread_t))) 221670f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher EXIT_UNSQUASH("Processors too large\n"); 221770f4aa66fa20ac3f86605e1330ccf241440e2cc3Phillip Lougher 22186697cff2155192a3e0c182a3cef046ebf215ac32plougher thread = malloc((3 + processors) * sizeof(pthread_t)); 22196697cff2155192a3e0c182a3cef046ebf215ac32plougher if(thread == NULL) 22208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 22213327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougher inflator_thread = &thread[3]; 22228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2223cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2224bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher * dimensioning the to_reader and to_inflate queues. The size of 2225cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * these queues is directly related to the amount of block 2226cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * read-ahead possible. To_reader queues block read requests to 2227bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher * the reader thread and to_inflate queues block decompression 22283327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougher * requests to the inflate thread(s) (once the block has been read by 2229cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the reader thread). The amount of read-ahead is determined by 2230cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * the combined size of the data_block and fragment caches which 2231cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * determine the total number of blocks which can be "in flight" 2232cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * at any one time (either being read or being decompressed) 2233cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2234cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * The maximum file open limit, however, affects the read-ahead 2235cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * possible, in that for normal sizes of the fragment and data block 2236cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches, where the incoming files have few data blocks or one fragment 2237cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * only, the file open limit is likely to be reached before the 2238cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * caches are full. This means the worst case sizing of the combined 2239cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * sizes of the caches is unlikely to ever be necessary. However, is is 2240cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * obvious read-ahead up to the data block cache size is always possible 2241cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * irrespective of the file open limit, because a single file could 2242cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * contain that number of blocks. 2243cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2244cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "file open limit + data block cache size" seems 2245cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * to be a reasonable estimate. We can reasonably assume the maximum 2246cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * likely read-ahead possible is data block cache size + one fragment 2247cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * per open file. 2248cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2249cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * dimensioning the to_writer queue. The size of this queue is 2250cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * directly related to the amount of block read-ahead possible. 2251bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher * However, unlike the to_reader and to_inflate queues, this is 2252cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * complicated by the fact the to_writer queue not only contains 2253cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * entries for fragments and data_blocks but it also contains 2254cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * file entries, one per open file in the read-ahead. 2255cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * 2256cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * Choosing the size as "2 * (file open limit) + 2257cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * data block cache size" seems to be a reasonable estimate. 2258cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * We can reasonably assume the maximum likely read-ahead possible 2259cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * is data block cache size + one fragment per open file, and then 2260cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * we will have a file_entry for each open file. 2261cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2262cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher res = getrlimit(RLIMIT_NOFILE, &rlim); 2263cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (res == -1) { 2264cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher ERROR("failed to get open file limit! Defaulting to 1\n"); 2265cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher rlim.rlim_cur = 1; 2266cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2267cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2268cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur != RLIM_INFINITY) { 2269cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2270cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * leave OPEN_FILE_MARGIN free (rlim_cur includes fds used by 2271cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * stdin, stdout, stderr and filesystem fd 2272cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2273cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (rlim.rlim_cur <= OPEN_FILE_MARGIN) 2274cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* no margin, use minimum possible */ 2275cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = 1; 2276cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher else 2277cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = rlim.rlim_cur - OPEN_FILE_MARGIN; 2278cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else 2279cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher max_files = -1; 2280cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2281cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* set amount of available files for use by open_wait and close_wake */ 2282cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher open_init(max_files); 2283cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2284cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher /* 2285bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher * allocate to_reader, to_inflate and to_writer queues. Set based on 2286cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * open file limit and cache size, unless open file limit is unlimited, 2287cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher * in which case set purely based on cache limits 22882b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 22892b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not overflow 22902b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * a signed int 2291cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher */ 2292cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher if (max_files != -1) { 22932b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(data_buffer_size, max_files) || 22942b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher add_overflow(data_buffer_size, max_files * 2)) 22952b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 22962b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2297cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(max_files + data_buffer_size); 2298bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher to_inflate = queue_init(max_files + data_buffer_size); 2299cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(max_files * 2 + data_buffer_size); 2300cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } else { 23012b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher int all_buffers_size; 23022b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23032b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(fragment_buffer_size, data_buffer_size)) 23042b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 23052b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 23062b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23072b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher all_buffers_size = fragment_buffer_size + data_buffer_size; 23082b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 23092b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(add_overflow(all_buffers_size, all_buffers_size)) 23102b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data and fragment queues combined are" 23112b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " too large\n"); 2312cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 2313cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_reader = queue_init(all_buffers_size); 2314bee9e37353d957d1c4d8669ca4eba30c2b9df3f5Phillip Lougher to_inflate = queue_init(all_buffers_size); 2315cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher to_writer = queue_init(all_buffers_size * 2); 2316cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher } 2317cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 23188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 2319cb32e1c6050eba57d59bef5a35a75ffc19d3c699Phillip Lougher 23208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 23218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 23228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 23238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 2324eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 2325fec0a36c9b8a2c91c2930ea57b304299490ccedfPhillip Lougher init_info(); 23268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 23278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 23293327bd9640ed579e8022b0e3889f71c342a64193Phillip Lougher if(pthread_create(&inflator_thread[i], NULL, inflator, NULL) != 2330c435240f52b78b0ef498118727ba8dad186db26bplougher 0) 23318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 23328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 23338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 23358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 23368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2337e0a306c5aca0aa2ca4d07593afaef79e360213a2Phillip Lougher if(pthread_sigmask(SIG_SETMASK, &old_mask, NULL) == -1) 23383642cef78fdbb9c4dc90cc6463443a6d005cfab2Phillip Lougher EXIT_UNSQUASH("Failed to set signal mask in initialise_threads" 2339c435240f52b78b0ef498118727ba8dad186db26bplougher "\n"); 23408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 23418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 23431b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 23441b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 23451b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2346ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher progress_enabled = progress; 23471b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 23481b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 23491b42101056befe25b5f19d5b099e806a2ecee9cdplougher 23501b42101056befe25b5f19d5b099e806a2ecee9cdplougher 23511b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 23521b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 23531b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 2354ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher if(progress_enabled) { 2355ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 2356ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher total_inodes - total_files + total_blocks, columns); 2357ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher printf("\n"); 2358ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher } 23591b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 23601b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 23611b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 23621b42101056befe25b5f19d5b099e806a2ecee9cdplougher 23631b42101056befe25b5f19d5b099e806a2ecee9cdplougher 23640100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Loughervoid progressbar_error(char *fmt, ...) 23650100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher{ 23660100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_list ap; 23670100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23680100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher pthread_mutex_lock(&screen_mutex); 23690100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23700100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher if(progress_enabled) 23710100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher fprintf(stderr, "\n"); 23720100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23730100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_start(ap, fmt); 23740100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher vfprintf(stderr, fmt, ap); 23750100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_end(ap); 23760100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23770100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher pthread_mutex_unlock(&screen_mutex); 23780100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher} 23790100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23800100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23810100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Loughervoid progressbar_info(char *fmt, ...) 23820100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher{ 23830100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_list ap; 23840100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23850100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher pthread_mutex_lock(&screen_mutex); 23860100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23870100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher if(progress_enabled) 23880100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher printf("\n"); 23890100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23900100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_start(ap, fmt); 23910100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher vprintf(fmt, ap); 23920100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher va_end(ap); 23930100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 23940100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher pthread_mutex_unlock(&screen_mutex); 23950100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher} 23960100fed4ec712daba9a0009c47f6e8390da5bd93Phillip Lougher 2397eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 2398eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 2399eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 2400b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher int max_digits, used, hashes, spaces; 2401dce832998340bea4236fddb5ba1525121044ce18plougher static int tty = -1; 2402eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2403b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher if(max == 0) 2404b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher return; 2405b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2406b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher max_digits = floor(log10(max)) + 1; 2407b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher used = max_digits * 2 + 11; 2408b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher hashes = (current * (columns - used)) / max; 2409b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher spaces = columns - used - hashes; 2410b5a32017ae5c8f1b4d00b296e8f6fef140e8dd99plougher 2411eaf639366792995c36ae7295bddf534f6f416643plougher if((current > max) || (columns - used < 0)) 2412eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 2413eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2414dce832998340bea4236fddb5ba1525121044ce18plougher if(tty == -1) 2415dce832998340bea4236fddb5ba1525121044ce18plougher tty = isatty(STDOUT_FILENO); 2416dce832998340bea4236fddb5ba1525121044ce18plougher if(!tty) { 2417dce832998340bea4236fddb5ba1525121044ce18plougher static long long previous = -1; 2418dce832998340bea4236fddb5ba1525121044ce18plougher 24190a0d045642e8e413f90b770539193d3fd1522786plougher /* 24200a0d045642e8e413f90b770539193d3fd1522786plougher * Updating much more frequently than this results in huge 24210a0d045642e8e413f90b770539193d3fd1522786plougher * log files. 24220a0d045642e8e413f90b770539193d3fd1522786plougher */ 2423dce832998340bea4236fddb5ba1525121044ce18plougher if((current % 100) != 0 && current != max) 2424dce832998340bea4236fddb5ba1525121044ce18plougher return; 2425dce832998340bea4236fddb5ba1525121044ce18plougher /* Don't update just to rotate the spinner. */ 2426dce832998340bea4236fddb5ba1525121044ce18plougher if(current == previous) 2427dce832998340bea4236fddb5ba1525121044ce18plougher return; 2428dce832998340bea4236fddb5ba1525121044ce18plougher previous = current; 2429dce832998340bea4236fddb5ba1525121044ce18plougher } 2430dce832998340bea4236fddb5ba1525121044ce18plougher 2431eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 2432eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2433eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 2434eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 2435eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2436eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 2437eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2438eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 2439eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 2440eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2441eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 2442eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 2443eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 2444eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 2445eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2446eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 24472b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougherint parse_number(char *arg, int *res) 24482b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher{ 24492b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher char *b; 24502b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher long number = strtol(arg, &b, 10); 24512b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24522b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check for trailing junk after number */ 24532b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(*b != '\0') 24542b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 24552b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24567f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher /* 24577f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * check for strtol underflow or overflow in conversion. 24587f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * Note: strtol can validly return LONG_MIN and LONG_MAX 24597f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * if the user entered these values, but, additional code 24607f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * to distinguish this scenario is unnecessary, because for 24617f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher * our purposes LONG_MIN and LONG_MAX are too large anyway 24627f1f61927a265b3c32f73afec110807b43dc1193Phillip Lougher */ 24632b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number == LONG_MIN || number == LONG_MAX) 24642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 24652b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24662b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* reject negative numbers as invalid */ 24672b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number < 0) 24682b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 24692b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24702b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* check if long result will overflow signed int */ 24712b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(number > INT_MAX) 24722b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 0; 24732b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24742b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher *res = number; 24752b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher return 1; 24762b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher} 24772b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 24782b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 2479443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 2480af304198183f3651ffbab317906dac1024ab61a5Phillip Lougher printf("unsquashfs version 4.3 (2014/05/12)\n");\ 2481cc06495ccafaf9bb7f3d078dee22f2e3b1af471cPhillip Lougher printf("copyright (C) 2014 Phillip Lougher "\ 248283d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher "<phillip@squashfs.org.uk>\n\n");\ 2483e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is free software; you can redistribute it and/or"\ 2484d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2485e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("modify it under the terms of the GNU General Public License"\ 2486d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2487e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("as published by the Free Software Foundation; either version "\ 2488e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "2,\n");\ 2489e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("or (at your option) any later version.\n\n");\ 2490e3206fad5b70e7e0527db2a627ad26616a8a2429plougher printf("This program is distributed in the hope that it will be "\ 2491e3206fad5b70e7e0527db2a627ad26616a8a2429plougher "useful,\n");\ 2492d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ 2493d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2494d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ 2495d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 2496443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 2497443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 2498443c15812032991c98b33b5424b17bcd55fe3575plougher{ 2499443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 2500b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 2501545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 2502a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 2503a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 2504e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher long long directory_table_end; 2505ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 2506ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 2507443c15812032991c98b33b5424b17bcd55fe3575plougher 25081b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 2509545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 2510545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 25119dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 25129dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 2513443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 2514443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 2515443c15812032991c98b33b5424b17bcd55fe3575plougher break; 2516d4204758f77acb5a371fa1487a755b76a05d5476plougher if(strcmp(argv[i], "-version") == 0 || 2517d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-v") == 0) { 2518443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 2519443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 2520d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-info") == 0 || 2521d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-i") == 0) 2522443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 2523c435240f52b78b0ef498118727ba8dad186db26bplougher else if(strcmp(argv[i], "-ls") == 0 || 2524c435240f52b78b0ef498118727ba8dad186db26bplougher strcmp(argv[i], "-l") == 0) 2525443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 2526d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-no-progress") == 0 || 2527d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-n") == 0) 2528296d7d8a68e33341d68f4354b5e1fe2f3aa275a6plougher progress = FALSE; 252931638061a6de0cb89093672aa71ddeb42f2eb28aplougher else if(strcmp(argv[i], "-no-xattrs") == 0 || 253031638061a6de0cb89093672aa71ddeb42f2eb28aplougher strcmp(argv[i], "-no") == 0) 253131638061a6de0cb89093672aa71ddeb42f2eb28aplougher no_xattrs = TRUE; 2532df9d38a515489c2c573754ad81abd230dfd8b1f0plougher else if(strcmp(argv[i], "-xattrs") == 0 || 2533df9d38a515489c2c573754ad81abd230dfd8b1f0plougher strcmp(argv[i], "-x") == 0) 2534df9d38a515489c2c573754ad81abd230dfd8b1f0plougher no_xattrs = FALSE; 2535498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher else if(strcmp(argv[i], "-user-xattrs") == 0 || 2536498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher strcmp(argv[i], "-u") == 0) { 2537498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher user_xattrs = TRUE; 2538498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher no_xattrs = FALSE; 2539498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher } else if(strcmp(argv[i], "-dest") == 0 || 2540d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-d") == 0) { 254171add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2542d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -dest missing filename\n", 2543d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 254471add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 254571add234b27054974d5e29f95b3fab3072792a62plougher } 2546443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 2547d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-processors") == 0 || 2548d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-p") == 0) { 2549c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 25502c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher !parse_number(argv[i], 25512c7ffbdfb7ef17a2032864e074a43d00631eeb8ePhillip Lougher &processors)) { 2552d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors missing or invalid " 2553d4204758f77acb5a371fa1487a755b76a05d5476plougher "processor number\n", argv[0]); 25540cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 25550cf5c297bec42c7c220d2825f12f9499f2293279plougher } 25560cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 2557d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors should be 1 or larger\n", 2558d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 25590cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 25600cf5c297bec42c7c220d2825f12f9499f2293279plougher } 2561d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-data-queue") == 0 || 2562d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-da") == 0) { 2563c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 25642b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 25652b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &data_buffer_size)) { 2566c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -data-queue missing or invalid " 2567c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2568ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2569ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2570ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 2571d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue should be 1 Mbyte or " 2572d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2573ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2574ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2575d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || 2576d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-fr") == 0) { 2577c435240f52b78b0ef498118727ba8dad186db26bplougher if((++i == argc) || 25782b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher !parse_number(argv[i], 25792b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher &fragment_buffer_size)) { 2580c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("%s: -frag-queue missing or invalid " 2581c435240f52b78b0ef498118727ba8dad186db26bplougher "queue size\n", argv[0]); 2582ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2583ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2584ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 2585d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue should be 1 Mbyte or " 2586d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 2587ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 2588ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 2589d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-force") == 0 || 2590d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-f") == 0) 2591a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 2592d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-stat") == 0 || 2593d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-s") == 0) 2594b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 2595d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-lls") == 0 || 2596d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-ll") == 0) { 25979baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 25989baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2599d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-linfo") == 0 || 2600d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-li") == 0) { 26019baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 26029baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 2603d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-ef") == 0 || 2604d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-e") == 0) { 260571add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2606d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -ef missing filename\n", 2607d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 260871add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 260971add234b27054974d5e29f95b3fab3072792a62plougher } 2610a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 2611d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-regex") == 0 || 2612d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-r") == 0) 26134dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 26144dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2615b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2616443c15812032991c98b33b5424b17bcd55fe3575plougher } 2617443c15812032991c98b33b5424b17bcd55fe3575plougher 2618feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher if(lsonly || info) 2619feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher progress = FALSE; 2620feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher 2621bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#ifdef SQUASHFS_TRACE 2622ce2c9c3d3741fb0285f20c6da2d0c73efd3bfa35Phillip Lougher /* 2623ce2c9c3d3741fb0285f20c6da2d0c73efd3bfa35Phillip Lougher * Disable progress bar if full debug tracing is enabled. 2624ce2c9c3d3741fb0285f20c6da2d0c73efd3bfa35Phillip Lougher * The progress bar in this case just gets in the way of the 2625ce2c9c3d3741fb0285f20c6da2d0c73efd3bfa35Phillip Lougher * debug trace output 2626ce2c9c3d3741fb0285f20c6da2d0c73efd3bfa35Phillip Lougher */ 2627bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher progress = FALSE; 2628bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#endif 2629bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher 2630443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2631443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2632443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 2633d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("SYNTAX: %s [options] filesystem [directories or " 2634d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract]\n", argv[0]); 2635d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-v[ersion]\t\tprint version, licence and " 2636d4204758f77acb5a371fa1487a755b76a05d5476plougher "copyright information\n"); 2637d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " 2638d4204758f77acb5a371fa1487a755b76a05d5476plougher "default \"squashfs-root\"\n"); 2639c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-n[o-progress]\t\tdon't display the progress " 2640c435240f52b78b0ef498118727ba8dad186db26bplougher "bar\n"); 2641df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" 2642df9d38a515489c2c573754ad81abd230dfd8b1f0plougher NOXOPT_STR"\n"); 2643df9d38a515489c2c573754ad81abd230dfd8b1f0plougher ERROR("\t-x[attrs]\t\textract xattrs in file system" 2644df9d38a515489c2c573754ad81abd230dfd8b1f0plougher XOPT_STR "\n"); 2645498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher ERROR("\t-u[ser-xattrs]\t\tonly extract user xattrs in " 2646498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher "file system.\n\t\t\t\tEnables extracting " 2647498da46ad7e6bd0a1fac0ec81d85ce1ac56bf385Phillip Lougher "xattrs\n"); 2648c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-p[rocessors] <number>\tuse <number> " 2649c435240f52b78b0ef498118727ba8dad186db26bplougher "processors. By default will use\n"); 2650c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tnumber of processors available\n"); 2651c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-i[nfo]\t\t\tprint files as they are " 2652c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed\n"); 2653c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-li[nfo]\t\tprint files as they are " 2654c435240f52b78b0ef498118727ba8dad186db26bplougher "unsquashed with file\n"); 2655c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tattributes (like ls -l output)\n"); 2656d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" 2657d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2658c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-ll[s]\t\t\tlist filesystem with file " 2659c435240f52b78b0ef498118727ba8dad186db26bplougher "attributes (like\n"); 2660c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\tls -l output), but don't unsquash\n"); 2661c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-f[orce]\t\tif file already exists then " 2662c435240f52b78b0ef498118727ba8dad186db26bplougher "overwrite\n"); 2663d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " 2664d4204758f77acb5a371fa1487a755b76a05d5476plougher "information\n"); 2665d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-e[f] <extract file>\tlist of directories or " 2666d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract.\n\t\t\t\tOne per line\n"); 2667c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-da[ta-queue] <size>\tSet data queue to " 2668c435240f52b78b0ef498118727ba8dad186db26bplougher "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", 2669d4204758f77acb5a371fa1487a755b76a05d5476plougher DATA_BUFFER_DEFAULT); 26708bc376ba1f7110fb88989e5134b74aa8412fb00eplougher ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " 2671d56f6723626a391b473c2c023b628abcd8ed31e3Phillip Lougher "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", 2672d4204758f77acb5a371fa1487a755b76a05d5476plougher FRAGMENT_BUFFER_DEFAULT); 2673c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX " 2674c435240f52b78b0ef498118727ba8dad186db26bplougher "regular expressions\n"); 2675c435240f52b78b0ef498118727ba8dad186db26bplougher ERROR("\t\t\t\trather than use the default shell " 2676c435240f52b78b0ef498118727ba8dad186db26bplougher "wildcard\n\t\t\t\texpansion (globbing)\n"); 2677076b053e2cce5c9172b4f385e866c2e606712a32plougher ERROR("\nDecompressors available:\n"); 2678076b053e2cce5c9172b4f385e866c2e606712a32plougher display_compressors("", ""); 2679443c15812032991c98b33b5424b17bcd55fe3575plougher } 2680443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2681443c15812032991c98b33b5424b17bcd55fe3575plougher } 2682443c15812032991c98b33b5424b17bcd55fe3575plougher 268371add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2684a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2685b54566f5c433764830c29c83151691d0034de094plougher 2686443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2687d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Could not open %s, because %s\n", argv[i], 2688d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 2689443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2690443c15812032991c98b33b5424b17bcd55fe3575plougher } 2691443c15812032991c98b33b5424b17bcd55fe3575plougher 269202bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2693443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2694443c15812032991c98b33b5424b17bcd55fe3575plougher 2695b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2696b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2697b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2698b624936abba03d38b7e9245c647339d8f6f34274plougher } 2699b624936abba03d38b7e9245c647339d8f6f34274plougher 270059b85a3abcbada8e2fdbfafb4c3dd2b91141d78fPhillip Lougher if(!check_compression(comp)) 2701f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher exit(1); 2702f025ee7d93e3ce56f1fdbd0661a89172500ba168plougher 270327c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_size = sBlk.s.block_size; 270427c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher block_log = sBlk.s.block_log; 2705ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2706009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher /* 27072b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Sanity check block size and block log. 27082b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 27092b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check they're within correct limits 27102b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 27112b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size > SQUASHFS_FILE_MAX_SIZE || 27122b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher block_log > SQUASHFS_FILE_MAX_LOG) 27132b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size or block_log too large." 27142b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 27152b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 27162b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 27172b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * Check block_size and block_log match 27182b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher */ 27192b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(block_size != (1 << block_log)) 27202b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Block size and block_log do not match." 27212b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher " File system is corrupt.\n"); 27222b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 27232b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher /* 2724009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher * convert from queue size in Mbytes to queue size in 27252b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * blocks. 27262b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * 27272b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * In doing so, check that the user supplied values do not 27282b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher * overflow a signed int 2729009263430d50ee32f3757c3c34d1f06262759f5dPhillip Lougher */ 27302b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(fragment_buffer_size, 20 - block_log)) 27312b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Fragment queue size is too large\n"); 27322b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 27332b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher fragment_buffer_size <<= 20 - block_log; 27342b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 27352b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher if(shift_overflow(data_buffer_size, 20 - block_log)) 27362b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher EXIT_UNSQUASH("Data queue size is too large\n"); 27372b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher else 27382b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher data_buffer_size <<= 20 - block_log; 27392b1aa06131c7d8d4361d79172afb9594e66a7280Phillip Lougher 27408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 27418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 274244a6967088416c9bd6ee7165bde59c9ba5ccb704plougher fragment_data = malloc(block_size); 274344a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(fragment_data == NULL) 2744443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2745443c15812032991c98b33b5424b17bcd55fe3575plougher 274644a6967088416c9bd6ee7165bde59c9ba5ccb704plougher file_data = malloc(block_size); 274744a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(file_data == NULL) 2748443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2749443c15812032991c98b33b5424b17bcd55fe3575plougher 275044a6967088416c9bd6ee7165bde59c9ba5ccb704plougher data = malloc(block_size); 275144a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(data == NULL) 2752eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2753443c15812032991c98b33b5424b17bcd55fe3575plougher 275444a6967088416c9bd6ee7165bde59c9ba5ccb704plougher created_inode = malloc(sBlk.s.inodes * sizeof(char *)); 275544a6967088416c9bd6ee7165bde59c9ba5ccb704plougher if(created_inode == NULL) 2756443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2757443c15812032991c98b33b5424b17bcd55fe3575plougher 275827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 2759443c15812032991c98b33b5424b17bcd55fe3575plougher 27601a7e7e871169a6cb6e3470a50b33db83830886e2plougher if(s_ops.read_uids_guids() == FALSE) 27611a7e7e871169a6cb6e3470a50b33db83830886e2plougher EXIT_UNSQUASH("failed to uid/gid table\n"); 2762ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2763e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher if(s_ops.read_fragment_table(&directory_table_end) == FALSE) 2764cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher EXIT_UNSQUASH("failed to read fragment table\n"); 2765ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 27661ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher if(read_inode_table(sBlk.s.inode_table_start, 27671ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher sBlk.s.directory_table_start) == FALSE) 27681ed1b1bfa19e9edd0e59da61d9f4c99021fb0b67Phillip Lougher EXIT_UNSQUASH("failed to read inode table\n"); 2769ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2770e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher if(read_directory_table(sBlk.s.directory_table_start, 2771e1542da6a3f99db8dc60b5cad891547e047861b7Phillip Lougher directory_table_end) == FALSE) 2772e89dabed981f39b54ca5046cfc2290dbe48961b5Phillip Lougher EXIT_UNSQUASH("failed to read directory table\n"); 2773443c15812032991c98b33b5424b17bcd55fe3575plougher 277431638061a6de0cb89093672aa71ddeb42f2eb28aplougher if(no_xattrs) 277531638061a6de0cb89093672aa71ddeb42f2eb28aplougher sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; 277631638061a6de0cb89093672aa71ddeb42f2eb28aplougher 27778935dc25479321709c74c2f8214cf5365669100eplougher if(read_xattrs_from_disk(fd, &sBlk.s) == 0) 27788935dc25479321709c74c2f8214cf5365669100eplougher EXIT_UNSQUASH("failed to read the xattr table\n"); 27798935dc25479321709c74c2f8214cf5365669100eplougher 2780a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2781a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2782a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2783a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2784a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 278527c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 278627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2787eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 278827c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); 27899b58176e667b67770569c9076a410b27aaa3bcf5plougher inode_number = 1; 2790eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2791c435240f52b78b0ef498118727ba8dad186db26bplougher printf("%d inodes (%d blocks) to write\n\n", total_inodes, 2792c435240f52b78b0ef498118727ba8dad186db26bplougher total_inodes - total_files + total_blocks); 2793eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2794ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher enable_progress_bar(); 27951b42101056befe25b5f19d5b099e806a2ecee9cdplougher 279627c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), 279727c4b6f7f6a33bf7711c0ee8cd563e4604dc5861plougher SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); 2798443c15812032991c98b33b5424b17bcd55fe3575plougher 27998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 28008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 28018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2802ff53fc094fa4760f2e4d602fd14ad6aa7a97cbe9Phillip Lougher disable_progress_bar(); 2803eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2804443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2805443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2806443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2807443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2808443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2809443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2810443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2811443c15812032991c98b33b5424b17bcd55fe3575plougher } 2812eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 28139dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2814443c15812032991c98b33b5424b17bcd55fe3575plougher} 2815