unsquashfs.c revision 01b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6
12f60990fb0352f7a30e0281a066458dbf033618bplougher/* 2443c15812032991c98b33b5424b17bcd55fe3575plougher * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. 3443c15812032991c98b33b5424b17bcd55fe3575plougher * 4d9b631e9e82c9e0d0e14b7f3d0f2965c523b113dplougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 579df93becb68081effabebba3006c794be308598plougher * Phillip Lougher <phillip@lougher.demon.co.uk> 6443c15812032991c98b33b5424b17bcd55fe3575plougher * 7443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is free software; you can redistribute it and/or 8443c15812032991c98b33b5424b17bcd55fe3575plougher * modify it under the terms of the GNU General Public License 9443c15812032991c98b33b5424b17bcd55fe3575plougher * as published by the Free Software Foundation; either version 2, 10443c15812032991c98b33b5424b17bcd55fe3575plougher * or (at your option) any later version. 11443c15812032991c98b33b5424b17bcd55fe3575plougher * 12443c15812032991c98b33b5424b17bcd55fe3575plougher * This program is distributed in the hope that it will be useful, 13443c15812032991c98b33b5424b17bcd55fe3575plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 14443c15812032991c98b33b5424b17bcd55fe3575plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15443c15812032991c98b33b5424b17bcd55fe3575plougher * GNU General Public License for more details. 16443c15812032991c98b33b5424b17bcd55fe3575plougher * 17443c15812032991c98b33b5424b17bcd55fe3575plougher * You should have received a copy of the GNU General Public License 18443c15812032991c98b33b5424b17bcd55fe3575plougher * along with this program; if not, write to the Free Software 19443c15812032991c98b33b5424b17bcd55fe3575plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20443c15812032991c98b33b5424b17bcd55fe3575plougher * 21ed5124f016834932db2c63d60d259d846171c216plougher * unsquashfs.c 22443c15812032991c98b33b5424b17bcd55fe3575plougher */ 23443c15812032991c98b33b5424b17bcd55fe3575plougher 24ed5124f016834932db2c63d60d259d846171c216plougher#include "unsquashfs.h" 256490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "squashfs_swap.h" 266490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "squashfs_compat.h" 276490378e5b5e8dc058daf28423a7465699a6ba7bplougher#include "read_fs.h" 288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 298888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *fragment_cache, *data_cache; 308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *to_reader, *to_deflate, *to_writer, *from_writer; 318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_t *thread, *deflator_thread; 328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherpthread_mutex_t fragment_mutex; 338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* user options that control parallelisation */ 358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherint processors = -1; 368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 376490378e5b5e8dc058daf28423a7465699a6ba7bplougherstruct super_block sBlk; 3802bc3bcabf2b219f63961f07293b83629948f026ploughersquashfs_operations s_ops; 3902bc3bcabf2b219f63961f07293b83629948f026plougher 409dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, 419dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher dev_count = 0, fifo_count = 0; 42443c15812032991c98b33b5424b17bcd55fe3575plougherchar *inode_table = NULL, *directory_table = NULL; 43443c15812032991c98b33b5424b17bcd55fe3575plougherstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; 44443c15812032991c98b33b5424b17bcd55fe3575plougherint fd; 45443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int *uid_table, *guid_table; 46443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int cached_frag = SQUASHFS_INVALID_FRAG; 47443c15812032991c98b33b5424b17bcd55fe3575plougherchar *fragment_data; 48443c15812032991c98b33b5424b17bcd55fe3575plougherchar *file_data; 49443c15812032991c98b33b5424b17bcd55fe3575plougherchar *data; 50443c15812032991c98b33b5424b17bcd55fe3575plougherunsigned int block_size; 51ae271cc93e3684d5314bcdc45b631e497ae43166plougherunsigned int block_log; 52d4204758f77acb5a371fa1487a755b76a05d5476plougherint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; 53d4204758f77acb5a371fa1487a755b76a05d5476plougherint use_regex = FALSE; 54443c15812032991c98b33b5424b17bcd55fe3575plougherchar **created_inode; 559dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint root_process; 56eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint columns; 57eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherint rotate = 0; 581b42101056befe25b5f19d5b099e806a2ecee9cdplougherpthread_mutex_t screen_mutex; 59eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherpthread_cond_t progress_wait; 601b42101056befe25b5f19d5b099e806a2ecee9cdplougherint progress = TRUE, progress_enabled = FALSE; 61eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int total_blocks = 0, total_files = 0, total_inodes = 0; 62eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougherunsigned int cur_blocks = 0; 63ed5124f016834932db2c63d60d259d846171c216plougherint inode_number = 1; 64443c15812032991c98b33b5424b17bcd55fe3575plougher 65476dcb48b24efff22caa970f000e151f1b28918dplougherint lookup_type[] = { 66476dcb48b24efff22caa970f000e151f1b28918dplougher 0, 67476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 68476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFREG, 69476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFLNK, 70476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFBLK, 71476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFCHR, 72476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFIFO, 73476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFSOCK, 74476dcb48b24efff22caa970f000e151f1b28918dplougher S_IFDIR, 75eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFREG, 76eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFLNK, 77eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFBLK, 78eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFCHR, 79eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFIFO, 80eabe4dbeaec52acc95278663d7a13da7384ef9baplougher S_IFSOCK 81476dcb48b24efff22caa970f000e151f1b28918dplougher}; 82476dcb48b24efff22caa970f000e151f1b28918dplougher 83476dcb48b24efff22caa970f000e151f1b28918dplougherstruct test table[] = { 84476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFSOCK, 0, 's' }, 85476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFLNK, 0, 'l' }, 86476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFBLK, 0, 'b' }, 87476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFDIR, 0, 'd' }, 88476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFCHR, 0, 'c' }, 89476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IFMT, S_IFIFO, 0, 'p' }, 90476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRUSR, S_IRUSR, 1, 'r' }, 91476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWUSR, S_IWUSR, 2, 'w' }, 92476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IRGRP, S_IRGRP, 4, 'r' }, 93476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWGRP, S_IWGRP, 5, 'w' }, 94476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IROTH, S_IROTH, 7, 'r' }, 95476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IWOTH, S_IWOTH, 8, 'w' }, 96476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, 97476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, 98476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, 99476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, 100476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, 101476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, 102476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, 103476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, 104476dcb48b24efff22caa970f000e151f1b28918dplougher { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, 1058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher { 0, 0, 0, 0} 1068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher}; 1078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 108eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns); 109eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar(); 110eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 111eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid sigwinch_handler() 112eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 113eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 114eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 115eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 116c27a3d72b339d80d38623a4ee5a42601338fb4c9plougher if(isatty(STDOUT_FILENO)) 117d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 118d4204758f77acb5a371fa1487a755b76a05d5476plougher "columns\n"); 119eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = 80; 120eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } else 121eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher columns = winsize.ws_col; 122eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1251b5f6c5145f284683a2628b73ab5f8a0e37dd7b4ploughervoid sigalrm_handler() 1261b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher{ 1271b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher rotate = (rotate + 1) % 4; 1281b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher} 1291b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1301b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 1318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct queue *queue_init(int size) 1328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct queue *queue = malloc(sizeof(struct queue)); 1348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(queue == NULL) 1368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 1378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { 1398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(queue); 1408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 1418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 1428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->size = size + 1; 1448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = queue->writep = 0; 1458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&queue->mutex, NULL); 1468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->empty, NULL); 1478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&queue->full, NULL); 1488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return queue; 1508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1538888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid queue_put(struct queue *queue, void *data) 1548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int nextp; 1568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while((nextp = (queue->writep + 1) % queue->size) == queue->readp) 1608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->full, &queue->mutex); 1618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->data[queue->writep] = data; 1638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->writep = nextp; 1648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->empty); 1658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 1668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1698888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *queue_get(struct queue *queue) 1708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher void *data; 1728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&queue->mutex); 1738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(queue->readp == queue->writep) 1758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_wait(&queue->empty, &queue->mutex); 1768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data = queue->data[queue->readp]; 1788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue->readp = (queue->readp + 1) % queue->size; 1798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_signal(&queue->full); 1808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&queue->mutex); 1818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return data; 1838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 1878888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_hash_table(struct cache *cache, struct cache_entry *entry) 1888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 1898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(entry->block); 1908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next = cache->hash_table[hash]; 1928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[hash] = entry; 1938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = NULL; 1948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 1958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry; 1968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 1978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2008888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_hash_table(struct cache *cache, struct cache_entry *entry) 2018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_prev) 2038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev->hash_next = entry->hash_next; 2048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 2058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; 2068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->hash_next) 2078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_next->hash_prev = entry->hash_prev; 2088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->hash_prev = entry->hash_next = NULL; 2108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2148888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid insert_free_list(struct cache *cache, struct cache_entry *entry) 2158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list) { 2178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next = cache->free_list; 2188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = cache->free_list->free_prev; 2198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev->free_next = entry; 2208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list->free_prev = entry; 2218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry; 2238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = entry; 2248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher/* Called with the cache mutex held */ 2298888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid remove_free_list(struct cache *cache, struct cache_entry *entry) 2308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2318888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->free_prev == NULL && entry->free_next == NULL) 2328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* not in free list */ 2338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return; 234222e49e257bccb10c0e608f071778f26fce28f01plougher else if(entry->free_prev == entry && entry->free_next == entry) { 2358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* only this entry in the free list */ 2368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 2388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher /* more than one entry in the free list */ 2398888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_next->free_prev = entry->free_prev; 2408888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev->free_next = entry->free_next; 2418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->free_list == entry) 2428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = entry->free_next; 2438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 2448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 2468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache *cache_init(int buffer_size, int max_buffers) 2508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 2518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache *cache = malloc(sizeof(struct cache)); 2528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache == NULL) 2548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 2558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->max_buffers = max_buffers; 2578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->buffer_size = buffer_size; 2588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count = 0; 2598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->free_list = NULL; 2608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); 2618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = FALSE; 2628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_pending = FALSE; 2638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&cache->mutex, NULL); 2648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_free, NULL); 2658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_init(&cache->wait_for_pending, NULL); 2668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return cache; 2688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 2698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherstruct cache_entry *cache_get(struct cache *cache, long long block, int size) 2728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 273d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 274d4204758f77acb5a371fa1487a755b76a05d5476plougher * Get a block out of the cache. If the block isn't in the cache 275d4204758f77acb5a371fa1487a755b76a05d5476plougher * it is added and queued to the reader() and deflate() threads for 276d4204758f77acb5a371fa1487a755b76a05d5476plougher * reading * off disk and decompression. The cache grows until max_blocks 277d4204758f77acb5a371fa1487a755b76a05d5476plougher * is reached, once this occurs existing discarded blocks on the free list 278d4204758f77acb5a371fa1487a755b76a05d5476plougher * are reused 279d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 2808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hash = CALCULATE_HASH(block); 2818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry; 2828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&cache->mutex); 2848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) 2868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->block == block) 2878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher break; 2888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry) { 290d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 291d4204758f77acb5a371fa1487a755b76a05d5476plougher *found the block in the cache, increment used count and 2928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * if necessary remove from free list so it won't disappear 2938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 2948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used ++; 2958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 2968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 2978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 298d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 299d4204758f77acb5a371fa1487a755b76a05d5476plougher * not in the cache 300d4204758f77acb5a371fa1487a755b76a05d5476plougher * 301d4204758f77acb5a371fa1487a755b76a05d5476plougher * first try to allocate new block 302d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(cache->count < cache->max_buffers) { 3048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = malloc(sizeof(struct cache_entry)); 3058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry == NULL) 3068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher goto failed; 3078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data = malloc(cache->buffer_size); 3088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->data == NULL) { 3098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(entry); 3108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher goto failed; 3118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache = cache; 3138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->free_prev = entry->free_next = NULL; 3148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->count ++; 3158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else { 316d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 317d4204758f77acb5a371fa1487a755b76a05d5476plougher * try to get from free list 318d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(cache->free_list == NULL) { 3208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache->wait_free = TRUE; 321d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&cache->wait_for_free, 322d4204758f77acb5a371fa1487a755b76a05d5476plougher &cache->mutex); 3238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3248888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry = cache->free_list; 3258888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_free_list(cache, entry); 3268888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher remove_hash_table(cache, entry); 3278888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3288888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 329d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 330d4204758f77acb5a371fa1487a755b76a05d5476plougher * initialise block and insert into the hash table 331d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->block = block; 3338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->size = size; 3348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used = 1; 3358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = FALSE; 3368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = TRUE; 3378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_hash_table(cache, entry); 3388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 339d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 340d4204758f77acb5a371fa1487a755b76a05d5476plougher * queue to read thread to read and ultimately (via the decompress 3418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * threads) decompress the buffer 3428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher */ 3438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3448888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_reader, entry); 3458888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return entry; 3488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3498888b61f8ff4680247d10f7e5beb2ff35e8c867dplougherfailed: 3508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&cache->mutex); 3518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher return NULL; 3528888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3538888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3558888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_ready(struct cache_entry *entry, int error) 3568888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 357d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 358d4204758f77acb5a371fa1487a755b76a05d5476plougher * mark cache entry as being complete, reading and (if necessary) 3598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * decompression has taken place, and the buffer is valid for use. 3608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * If an error occurs reading or decompressing, the buffer also 361d4204758f77acb5a371fa1487a755b76a05d5476plougher * becomes ready but with an error... 362d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->pending = FALSE; 3658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->error = error; 3668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 367d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 368d4204758f77acb5a371fa1487a755b76a05d5476plougher * if the wait_pending flag is set, one or more threads may be waiting on 369d4204758f77acb5a371fa1487a755b76a05d5476plougher * this buffer 370d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_pending) { 3728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = FALSE; 3738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_pending); 3748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 3778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3808888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_wait(struct cache_entry *entry) 3818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 382d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 383d4204758f77acb5a371fa1487a755b76a05d5476plougher * wait for this cache entry to become ready, when reading and (if 384d4204758f77acb5a371fa1487a755b76a05d5476plougher * necessary) decompression has taken place 385d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 3868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 3878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(entry->pending) { 3898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_pending = TRUE; 390d4204758f77acb5a371fa1487a755b76a05d5476plougher pthread_cond_wait(&entry->cache->wait_for_pending, 391d4204758f77acb5a371fa1487a755b76a05d5476plougher &entry->cache->mutex); 3928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 3938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 3958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 3968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 3988888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid cache_block_put(struct cache_entry *entry) 3998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 400d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 401d4204758f77acb5a371fa1487a755b76a05d5476plougher * finished with this cache entry, once the usage count reaches zero it 4028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * can be reused and is put onto the free list. As it remains accessible 4038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * via the hash table it can be found getting a new lease of life before it 404d4204758f77acb5a371fa1487a755b76a05d5476plougher * is reused. 405d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_lock(&entry->cache->mutex); 4078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->used --; 4098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->used == 0) { 4108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher insert_free_list(entry->cache, entry); 4118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 412d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 413d4204758f77acb5a371fa1487a755b76a05d5476plougher * if the wait_free flag is set, one or more threads may be waiting 414d4204758f77acb5a371fa1487a755b76a05d5476plougher * on this buffer 415d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 4168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(entry->cache->wait_free) { 4178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->cache->wait_free = FALSE; 4188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_cond_broadcast(&entry->cache->wait_for_free); 4198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 4218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 4228888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_unlock(&entry->cache->mutex); 4238888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 424476dcb48b24efff22caa970f000e151f1b28918dplougher 425476dcb48b24efff22caa970f000e151f1b28918dplougher 426476dcb48b24efff22caa970f000e151f1b28918dplougherchar *modestr(char *str, int mode) 427476dcb48b24efff22caa970f000e151f1b28918dplougher{ 428476dcb48b24efff22caa970f000e151f1b28918dplougher int i; 429476dcb48b24efff22caa970f000e151f1b28918dplougher 430476dcb48b24efff22caa970f000e151f1b28918dplougher strcpy(str, "----------"); 431476dcb48b24efff22caa970f000e151f1b28918dplougher 432476dcb48b24efff22caa970f000e151f1b28918dplougher for(i = 0; table[i].mask != 0; i++) { 433476dcb48b24efff22caa970f000e151f1b28918dplougher if((mode & table[i].mask) == table[i].value) 434476dcb48b24efff22caa970f000e151f1b28918dplougher str[table[i].position] = table[i].mode; 435476dcb48b24efff22caa970f000e151f1b28918dplougher } 436476dcb48b24efff22caa970f000e151f1b28918dplougher 437476dcb48b24efff22caa970f000e151f1b28918dplougher return str; 438476dcb48b24efff22caa970f000e151f1b28918dplougher} 439476dcb48b24efff22caa970f000e151f1b28918dplougher 440476dcb48b24efff22caa970f000e151f1b28918dplougher 4413edfa57b6a463f7d441d995559143f4861d62e98plougher#define TOTALCHARS 25 4426f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint print_filename(char *pathname, struct inode *inode) 443476dcb48b24efff22caa970f000e151f1b28918dplougher{ 4446f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher char str[11], dummy[100], dummy2[100], *userstr, *groupstr; 4456f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int padchars; 446476dcb48b24efff22caa970f000e151f1b28918dplougher struct passwd *user; 447476dcb48b24efff22caa970f000e151f1b28918dplougher struct group *group; 44888facddfd83e48a907b82210ddccbb4f84d80aecplougher struct tm *t; 449476dcb48b24efff22caa970f000e151f1b28918dplougher 450476dcb48b24efff22caa970f000e151f1b28918dplougher if(short_ls) { 451476dcb48b24efff22caa970f000e151f1b28918dplougher printf("%s\n", pathname); 452476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 453476dcb48b24efff22caa970f000e151f1b28918dplougher } 454476dcb48b24efff22caa970f000e151f1b28918dplougher 4556f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((user = getpwuid(inode->uid)) == NULL) { 4566f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy, "%d", inode->uid); 4573edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = dummy; 4583edfa57b6a463f7d441d995559143f4861d62e98plougher } else 4593edfa57b6a463f7d441d995559143f4861d62e98plougher userstr = user->pw_name; 4603edfa57b6a463f7d441d995559143f4861d62e98plougher 4616f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((group = getgrgid(inode->gid)) == NULL) { 4626f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher sprintf(dummy2, "%d", inode->gid); 4633edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = dummy2; 4643edfa57b6a463f7d441d995559143f4861d62e98plougher } else 4653edfa57b6a463f7d441d995559143f4861d62e98plougher groupstr = group->gr_name; 4663edfa57b6a463f7d441d995559143f4861d62e98plougher 4676f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); 4683edfa57b6a463f7d441d995559143f4861d62e98plougher 4696f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(inode->mode & S_IFMT) { 4703edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFREG: 4713edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFDIR: 4723edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFSOCK: 4733edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFIFO: 4743edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFLNK: 4753edfa57b6a463f7d441d995559143f4861d62e98plougher padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); 4763edfa57b6a463f7d441d995559143f4861d62e98plougher 477caf2f0f593c7f14a4e7e151eeeed773c72578f69plougher printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); 4783edfa57b6a463f7d441d995559143f4861d62e98plougher break; 4793edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFCHR: 4803edfa57b6a463f7d441d995559143f4861d62e98plougher case S_IFBLK: 4813edfa57b6a463f7d441d995559143f4861d62e98plougher padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; 4823edfa57b6a463f7d441d995559143f4861d62e98plougher 483d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", 484d4204758f77acb5a371fa1487a755b76a05d5476plougher (int) inode->data >> 8, (int) inode->data & 0xff); 4853edfa57b6a463f7d441d995559143f4861d62e98plougher break; 4863edfa57b6a463f7d441d995559143f4861d62e98plougher } 487476dcb48b24efff22caa970f000e151f1b28918dplougher 4886f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher t = localtime(&inode->time); 48988facddfd83e48a907b82210ddccbb4f84d80aecplougher 490d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, 491d4204758f77acb5a371fa1487a755b76a05d5476plougher t->tm_mday, t->tm_hour, t->tm_min, pathname); 4926f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((inode->mode & S_IFMT) == S_IFLNK) 4936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher printf(" -> %s", inode->symlink); 4943edfa57b6a463f7d441d995559143f4861d62e98plougher printf("\n"); 4953edfa57b6a463f7d441d995559143f4861d62e98plougher 496476dcb48b24efff22caa970f000e151f1b28918dplougher return 1; 497476dcb48b24efff22caa970f000e151f1b28918dplougher} 498476dcb48b24efff22caa970f000e151f1b28918dplougher 499443c15812032991c98b33b5424b17bcd55fe3575plougher 500f404f4914fdb272a70e18664e8963d793cc90f44plougherint add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) 501443c15812032991c98b33b5424b17bcd55fe3575plougher{ 502443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 503443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 504443c15812032991c98b33b5424b17bcd55fe3575plougher 505443c15812032991c98b33b5424b17bcd55fe3575plougher if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { 506443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("add_hash: out of memory in malloc\n"); 507443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 508443c15812032991c98b33b5424b17bcd55fe3575plougher } 509443c15812032991c98b33b5424b17bcd55fe3575plougher 510443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->start = start; 511443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->bytes = bytes; 512443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table_entry->next = hash_table[hash]; 513443c15812032991c98b33b5424b17bcd55fe3575plougher hash_table[hash] = hash_table_entry; 514443c15812032991c98b33b5424b17bcd55fe3575plougher 515443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 516443c15812032991c98b33b5424b17bcd55fe3575plougher} 517443c15812032991c98b33b5424b17bcd55fe3575plougher 518443c15812032991c98b33b5424b17bcd55fe3575plougher 519f404f4914fdb272a70e18664e8963d793cc90f44plougherint lookup_entry(struct hash_table_entry *hash_table[], long long start) 520443c15812032991c98b33b5424b17bcd55fe3575plougher{ 521443c15812032991c98b33b5424b17bcd55fe3575plougher int hash = CALCULATE_HASH(start); 522443c15812032991c98b33b5424b17bcd55fe3575plougher struct hash_table_entry *hash_table_entry; 523443c15812032991c98b33b5424b17bcd55fe3575plougher 5249dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher for(hash_table_entry = hash_table[hash]; hash_table_entry; 5259dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher hash_table_entry = hash_table_entry->next) 5267a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher 527443c15812032991c98b33b5424b17bcd55fe3575plougher if(hash_table_entry->start == start) 528443c15812032991c98b33b5424b17bcd55fe3575plougher return hash_table_entry->bytes; 529443c15812032991c98b33b5424b17bcd55fe3575plougher 530443c15812032991c98b33b5424b17bcd55fe3575plougher return -1; 531443c15812032991c98b33b5424b17bcd55fe3575plougher} 532443c15812032991c98b33b5424b17bcd55fe3575plougher 533443c15812032991c98b33b5424b17bcd55fe3575plougher 534443c15812032991c98b33b5424b17bcd55fe3575plougherint read_bytes(long long byte, int bytes, char *buff) 535443c15812032991c98b33b5424b17bcd55fe3575plougher{ 536443c15812032991c98b33b5424b17bcd55fe3575plougher off_t off = byte; 537d7f3de3408089ce187d8bc26f6072730c77628daplougher int res, count; 538443c15812032991c98b33b5424b17bcd55fe3575plougher 539fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); 540fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 541443c15812032991c98b33b5424b17bcd55fe3575plougher if(lseek(fd, off, SEEK_SET) == -1) { 5425d415c6659faaa7a69c9baa7175610d889747142plougher ERROR("Lseek failed because %s\n", strerror(errno)); 543443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 544443c15812032991c98b33b5424b17bcd55fe3575plougher } 545443c15812032991c98b33b5424b17bcd55fe3575plougher 546d7f3de3408089ce187d8bc26f6072730c77628daplougher for(count = 0; count < bytes; count += res) { 547d7f3de3408089ce187d8bc26f6072730c77628daplougher res = read(fd, buff + count, bytes - count); 548d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res < 1) { 549d7f3de3408089ce187d8bc26f6072730c77628daplougher if(res == 0) { 550d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because EOF\n"); 551d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 552d7f3de3408089ce187d8bc26f6072730c77628daplougher } else if(errno != EINTR) { 553d7f3de3408089ce187d8bc26f6072730c77628daplougher ERROR("Read on filesystem failed because %s\n", 554d7f3de3408089ce187d8bc26f6072730c77628daplougher strerror(errno)); 555d7f3de3408089ce187d8bc26f6072730c77628daplougher return FALSE; 556d7f3de3408089ce187d8bc26f6072730c77628daplougher } else 557d7f3de3408089ce187d8bc26f6072730c77628daplougher res = 0; 558d7f3de3408089ce187d8bc26f6072730c77628daplougher } 559443c15812032991c98b33b5424b17bcd55fe3575plougher } 560443c15812032991c98b33b5424b17bcd55fe3575plougher 561443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 562443c15812032991c98b33b5424b17bcd55fe3575plougher} 563443c15812032991c98b33b5424b17bcd55fe3575plougher 564443c15812032991c98b33b5424b17bcd55fe3575plougher 56502bc3bcabf2b219f63961f07293b83629948f026plougherint read_block(long long start, long long *next, char *block) 566443c15812032991c98b33b5424b17bcd55fe3575plougher{ 567443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned short c_byte; 568443c15812032991c98b33b5424b17bcd55fe3575plougher int offset = 2; 569443c15812032991c98b33b5424b17bcd55fe3575plougher 570443c15812032991c98b33b5424b17bcd55fe3575plougher if(swap) { 571443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, block) == FALSE) 572fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 573443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[1] = block[0]; 574443c15812032991c98b33b5424b17bcd55fe3575plougher ((unsigned char *) &c_byte)[0] = block[1]; 575443c15812032991c98b33b5424b17bcd55fe3575plougher } else 576443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, 2, (char *)&c_byte) == FALSE) 577fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 578fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 579d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_block: block @0x%llx, %d %s bytes\n", start, 580d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? 581d4204758f77acb5a371fa1487a755b76a05d5476plougher "compressed" : "uncompressed"); 582443c15812032991c98b33b5424b17bcd55fe3575plougher 58302bc3bcabf2b219f63961f07293b83629948f026plougher if(SQUASHFS_CHECK_DATA(sBlk.flags)) 584443c15812032991c98b33b5424b17bcd55fe3575plougher offset = 3; 585443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED(c_byte)) { 586443c15812032991c98b33b5424b17bcd55fe3575plougher char buffer[SQUASHFS_METADATA_SIZE]; 587443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 588443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = SQUASHFS_METADATA_SIZE; 589443c15812032991c98b33b5424b17bcd55fe3575plougher 590443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 591443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, buffer) == FALSE) 592fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 593443c15812032991c98b33b5424b17bcd55fe3575plougher 594d4204758f77acb5a371fa1487a755b76a05d5476plougher res = uncompress((unsigned char *) block, &bytes, 595d4204758f77acb5a371fa1487a755b76a05d5476plougher (const unsigned char *) buffer, c_byte); 596545404219cdd79c1e06ac7d0698d02a15240c4c3plougher 597545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(res != Z_OK) { 598443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 599d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough memory" 600d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 601443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 602d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough room " 603d4204758f77acb5a371fa1487a755b76a05d5476plougher "in output buffer\n"); 604443c15812032991c98b33b5424b17bcd55fe3575plougher else 605d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, unknown error " 606d4204758f77acb5a371fa1487a755b76a05d5476plougher "%d\n", res); 607fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 608443c15812032991c98b33b5424b17bcd55fe3575plougher } 609443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 610443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 611443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 612443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 613443c15812032991c98b33b5424b17bcd55fe3575plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 614443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start + offset, c_byte, block) == FALSE) 615fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher goto failed; 616443c15812032991c98b33b5424b17bcd55fe3575plougher if(next) 617443c15812032991c98b33b5424b17bcd55fe3575plougher *next = start + offset + c_byte; 618443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 619443c15812032991c98b33b5424b17bcd55fe3575plougher } 620fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 621fe3ca0609d02d78bcd11637c1220b2ff428f466aplougherfailed: 62268ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher ERROR("read_block: failed to read block @0x%llx\n", start); 623fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher return FALSE; 624443c15812032991c98b33b5424b17bcd55fe3575plougher} 625443c15812032991c98b33b5424b17bcd55fe3575plougher 626443c15812032991c98b33b5424b17bcd55fe3575plougher 627443c15812032991c98b33b5424b17bcd55fe3575plougherint read_data_block(long long start, unsigned int size, char *block) 628443c15812032991c98b33b5424b17bcd55fe3575plougher{ 629443c15812032991c98b33b5424b17bcd55fe3575plougher int res; 630443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned long bytes = block_size; 631443c15812032991c98b33b5424b17bcd55fe3575plougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); 632443c15812032991c98b33b5424b17bcd55fe3575plougher 633d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, 634d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), 635d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); 636fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 637443c15812032991c98b33b5424b17bcd55fe3575plougher if(SQUASHFS_COMPRESSED_BLOCK(size)) { 638443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, data) == FALSE) 63968ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 640443c15812032991c98b33b5424b17bcd55fe3575plougher 641d4204758f77acb5a371fa1487a755b76a05d5476plougher res = uncompress((unsigned char *) block, &bytes, 642d4204758f77acb5a371fa1487a755b76a05d5476plougher (const unsigned char *) data, c_byte); 643545404219cdd79c1e06ac7d0698d02a15240c4c3plougher 644545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(res != Z_OK) { 645443c15812032991c98b33b5424b17bcd55fe3575plougher if(res == Z_MEM_ERROR) 646d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough memory" 647d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 648443c15812032991c98b33b5424b17bcd55fe3575plougher else if(res == Z_BUF_ERROR) 649d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough room " 650d4204758f77acb5a371fa1487a755b76a05d5476plougher "in output buffer\n"); 651443c15812032991c98b33b5424b17bcd55fe3575plougher else 652d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, unknown error " 653d4204758f77acb5a371fa1487a755b76a05d5476plougher "%d\n", res); 65468ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 655443c15812032991c98b33b5424b17bcd55fe3575plougher } 656443c15812032991c98b33b5424b17bcd55fe3575plougher 657443c15812032991c98b33b5424b17bcd55fe3575plougher return bytes; 658443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 659443c15812032991c98b33b5424b17bcd55fe3575plougher if(read_bytes(start, c_byte, block) == FALSE) 66068ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher goto failed; 661443c15812032991c98b33b5424b17bcd55fe3575plougher 662443c15812032991c98b33b5424b17bcd55fe3575plougher return c_byte; 663443c15812032991c98b33b5424b17bcd55fe3575plougher } 66468ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher 66568ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougherfailed: 666d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, 667d4204758f77acb5a371fa1487a755b76a05d5476plougher size); 66868ba26e4a9ee62315d5d2bf5c23bfbc02347b646plougher return FALSE; 669443c15812032991c98b33b5424b17bcd55fe3575plougher} 670443c15812032991c98b33b5424b17bcd55fe3575plougher 671443c15812032991c98b33b5424b17bcd55fe3575plougher 67202bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_inode_table(long long start, long long end) 673443c15812032991c98b33b5424b17bcd55fe3575plougher{ 674443c15812032991c98b33b5424b17bcd55fe3575plougher int size = 0, bytes = 0, res; 675443c15812032991c98b33b5424b17bcd55fe3575plougher 67641da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); 677443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 678443c15812032991c98b33b5424b17bcd55fe3575plougher if((size - bytes < SQUASHFS_METADATA_SIZE) && 6799dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher ((inode_table = realloc(inode_table, size += 6809dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher SQUASHFS_METADATA_SIZE)) == NULL)) 681d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_inode_table: out of memory in " 682d4204758f77acb5a371fa1487a755b76a05d5476plougher "realloc\n"); 683443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_inode_table: reading block 0x%llx\n", start); 684443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(inode_table_hash, start, bytes); 68502bc3bcabf2b219f63961f07293b83629948f026plougher if((res = read_block(start, &start, inode_table + bytes)) == 0) { 686443c15812032991c98b33b5424b17bcd55fe3575plougher free(inode_table); 687d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_inode_table: failed to read " 688d4204758f77acb5a371fa1487a755b76a05d5476plougher "block \n"); 689443c15812032991c98b33b5424b17bcd55fe3575plougher } 690443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 691443c15812032991c98b33b5424b17bcd55fe3575plougher } 692443c15812032991c98b33b5424b17bcd55fe3575plougher} 693443c15812032991c98b33b5424b17bcd55fe3575plougher 694443c15812032991c98b33b5424b17bcd55fe3575plougher 695d4204758f77acb5a371fa1487a755b76a05d5476plougherint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, 696d4204758f77acb5a371fa1487a755b76a05d5476plougher unsigned int set_mode) 697443c15812032991c98b33b5424b17bcd55fe3575plougher{ 6986f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher struct utimbuf times = { time, time }; 699443c15812032991c98b33b5424b17bcd55fe3575plougher 700443c15812032991c98b33b5424b17bcd55fe3575plougher if(utime(pathname, ×) == -1) { 701d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to set time on %s, because %s\n", 702d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 703443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 704443c15812032991c98b33b5424b17bcd55fe3575plougher } 705443c15812032991c98b33b5424b17bcd55fe3575plougher 7069dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 7076f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(chown(pathname, uid, guid) == -1) { 708d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change uid and gids on " 709d4204758f77acb5a371fa1487a755b76a05d5476plougher "%s, because %s\n", pathname, strerror(errno)); 710443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 711443c15812032991c98b33b5424b17bcd55fe3575plougher } 7129dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher } else 7139dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher mode &= ~07000; 7149dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 7159dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { 716d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("set_attributes: failed to change mode %s, because %s\n", 717d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 7189dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return FALSE; 719443c15812032991c98b33b5424b17bcd55fe3575plougher } 720443c15812032991c98b33b5424b17bcd55fe3575plougher 721443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 722443c15812032991c98b33b5424b17bcd55fe3575plougher} 723443c15812032991c98b33b5424b17bcd55fe3575plougher 724443c15812032991c98b33b5424b17bcd55fe3575plougher 7251c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougherint write_bytes(int fd, char *buff, int bytes) 7261c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher{ 7271c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher int res, count; 7281c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7291c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher for(count = 0; count < bytes; count += res) { 7301c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = write(fd, buff + count, bytes - count); 7311c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(res == -1) { 7321c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(errno != EINTR) { 7331c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher ERROR("Write on output file failed because %s\n", 7341c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher strerror(errno)); 7351c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return -1; 7361c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7371c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher res = 0; 7381c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7391c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher } 7401c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7411c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher return 0; 7421c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher} 7431c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 7441c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher 745b9cee889506e674726856035dba52d5e1cceeb99plougherint lseek_broken = FALSE; 746c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherchar *zero_data = NULL; 747b9cee889506e674726856035dba52d5e1cceeb99plougher 748c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougherint write_block(int file_fd, char *buffer, int size, int hole, int sparse) 749b9cee889506e674726856035dba52d5e1cceeb99plougher{ 750b9cee889506e674726856035dba52d5e1cceeb99plougher off_t off = hole; 751b9cee889506e674726856035dba52d5e1cceeb99plougher 752b9cee889506e674726856035dba52d5e1cceeb99plougher if(hole) { 753c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse && lseek_broken == FALSE) { 754c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error = lseek(file_fd, off, SEEK_CUR); 755c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == -1) 756c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher /* failed to seek beyond end of file */ 757c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher lseek_broken = TRUE; 758c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher } 759c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 760c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if((sparse == FALSE || lseek_broken) && zero_data == NULL) { 761b9cee889506e674726856035dba52d5e1cceeb99plougher if((zero_data = malloc(block_size)) == NULL) 762d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("write_block: failed to alloc zero " 763d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 764b9cee889506e674726856035dba52d5e1cceeb99plougher memset(zero_data, 0, block_size); 765b9cee889506e674726856035dba52d5e1cceeb99plougher } 766c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 767c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(sparse == FALSE || lseek_broken) { 768b9cee889506e674726856035dba52d5e1cceeb99plougher int blocks = (hole + block_size -1) / block_size; 769b9cee889506e674726856035dba52d5e1cceeb99plougher int avail_bytes, i; 770b9cee889506e674726856035dba52d5e1cceeb99plougher for(i = 0; i < blocks; i++, hole -= avail_bytes) { 771d4204758f77acb5a371fa1487a755b76a05d5476plougher avail_bytes = hole > block_size ? block_size : 772d4204758f77acb5a371fa1487a755b76a05d5476plougher hole; 773d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_bytes(file_fd, zero_data, avail_bytes) 774d4204758f77acb5a371fa1487a755b76a05d5476plougher == -1) 775b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 776b9cee889506e674726856035dba52d5e1cceeb99plougher } 777b9cee889506e674726856035dba52d5e1cceeb99plougher } 778b9cee889506e674726856035dba52d5e1cceeb99plougher } 779b9cee889506e674726856035dba52d5e1cceeb99plougher 7801c5d8b0e7c8e68373eeb28311f9f9ccae2d9c617plougher if(write_bytes(file_fd, buffer, size) == -1) 781b9cee889506e674726856035dba52d5e1cceeb99plougher goto failure; 782b9cee889506e674726856035dba52d5e1cceeb99plougher 783b9cee889506e674726856035dba52d5e1cceeb99plougher return TRUE; 784b9cee889506e674726856035dba52d5e1cceeb99plougher 785b9cee889506e674726856035dba52d5e1cceeb99plougherfailure: 786b9cee889506e674726856035dba52d5e1cceeb99plougher return FALSE; 787b9cee889506e674726856035dba52d5e1cceeb99plougher} 788b9cee889506e674726856035dba52d5e1cceeb99plougher 7898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 79079df93becb68081effabebba3006c794be308598plougherint write_file(struct inode *inode, char *pathname) 791443c15812032991c98b33b5424b17bcd55fe3575plougher{ 7928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned int file_fd, i; 793f9c72b137336d5c1d4bdf2792f2bc5142713676bplougher unsigned int *block_list; 79479df93becb68081effabebba3006c794be308598plougher int file_end = inode->data / block_size; 79579df93becb68081effabebba3006c794be308598plougher long long start = inode->start; 7968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file; 797443c15812032991c98b33b5424b17bcd55fe3575plougher 79879df93becb68081effabebba3006c794be308598plougher TRACE("write_file: regular file, blocks %d\n", inode->blocks); 799443c15812032991c98b33b5424b17bcd55fe3575plougher 800d4204758f77acb5a371fa1487a755b76a05d5476plougher file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), 801d4204758f77acb5a371fa1487a755b76a05d5476plougher (mode_t) inode->mode & 0777); 802d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file_fd == -1) { 803d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("write_file: failed to create file %s, because %s\n", 804d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 805443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 806443c15812032991c98b33b5424b17bcd55fe3575plougher } 807443c15812032991c98b33b5424b17bcd55fe3575plougher 80879df93becb68081effabebba3006c794be308598plougher if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) 8098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc block list\n"); 810443c15812032991c98b33b5424b17bcd55fe3575plougher 81179df93becb68081effabebba3006c794be308598plougher s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); 812443c15812032991c98b33b5424b17bcd55fe3575plougher 8138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if((file = malloc(sizeof(struct squashfs_file))) == NULL) 8148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 815443c15812032991c98b33b5424b17bcd55fe3575plougher 816d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 817d4204758f77acb5a371fa1487a755b76a05d5476plougher * the writer thread is queued a squashfs_file structure describing the 8188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * file. If the file has one or more blocks or a fragments they are queued 819d4204758f77acb5a371fa1487a755b76a05d5476plougher * separately (references to blocks in the cache). 820d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 8218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file->fd = file_fd; 82279df93becb68081effabebba3006c794be308598plougher file->file_size = inode->data; 82379df93becb68081effabebba3006c794be308598plougher file->mode = inode->mode; 82479df93becb68081effabebba3006c794be308598plougher file->gid = inode->gid; 82579df93becb68081effabebba3006c794be308598plougher file->uid = inode->uid; 82679df93becb68081effabebba3006c794be308598plougher file->time = inode->time; 82779df93becb68081effabebba3006c794be308598plougher file->pathname = strdup(pathname); 82879df93becb68081effabebba3006c794be308598plougher file->blocks = inode->blocks + (inode->frag_bytes > 0); 8297f6692575a1b1c8d7d55afac647b72b84b79e378plougher file->sparse = inode->sparse; 8308888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, file); 831443c15812032991c98b33b5424b17bcd55fe3575plougher 83279df93becb68081effabebba3006c794be308598plougher for(i = 0; i < inode->blocks; i++) { 8338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); 8348372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 8358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 8368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 8378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 8388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->offset = 0; 839d4204758f77acb5a371fa1487a755b76a05d5476plougher block->size = i == file_end ? inode->data & (block_size - 1) : 840d4204758f77acb5a371fa1487a755b76a05d5476plougher block_size; 8418888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block_list[i] == 0) /* sparse file */ 8428888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = NULL; 8438888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else { 844d4204758f77acb5a371fa1487a755b76a05d5476plougher block->buffer = cache_get(data_cache, start, 845d4204758f77acb5a371fa1487a755b76a05d5476plougher block_list[i]); 8468888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == NULL) 8478888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: cache_get failed\n"); 8488888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher start += c_byte; 849443c15812032991c98b33b5424b17bcd55fe3575plougher } 8508888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 851443c15812032991c98b33b5424b17bcd55fe3575plougher } 852443c15812032991c98b33b5424b17bcd55fe3575plougher 85379df93becb68081effabebba3006c794be308598plougher if(inode->frag_bytes) { 8548888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int size; 8558888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher long long start; 8568372232d2460411adaa2299c32a0a88665e44902plougher struct file_entry *block = malloc(sizeof(struct file_entry)); 8578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 8588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block == NULL) 8598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: unable to malloc file\n"); 86079df93becb68081effabebba3006c794be308598plougher s_ops.read_fragment(inode->fragment, &start, &size); 8618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher block->buffer = cache_get(fragment_cache, start, size); 8628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == NULL) 8638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("write_file: cache_get failed\n"); 86479df93becb68081effabebba3006c794be308598plougher block->offset = inode->offset; 86579df93becb68081effabebba3006c794be308598plougher block->size = inode->frag_bytes; 8668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, block); 867b9cee889506e674726856035dba52d5e1cceeb99plougher } 868b9cee889506e674726856035dba52d5e1cceeb99plougher 869b9cee889506e674726856035dba52d5e1cceeb99plougher free(block_list); 870443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 871443c15812032991c98b33b5424b17bcd55fe3575plougher} 872476dcb48b24efff22caa970f000e151f1b28918dplougher 873476dcb48b24efff22caa970f000e151f1b28918dplougher 8746f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougherint create_inode(char *pathname, struct inode *i) 875443c15812032991c98b33b5424b17bcd55fe3575plougher{ 8766f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher TRACE("create_inode: pathname %s\n", pathname); 877443c15812032991c98b33b5424b17bcd55fe3575plougher 8786f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(created_inode[i->inode_number - 1]) { 879443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: hard link\n"); 8806013a30bd39550decc2546a47e5168e57bfcfde8plougher if(force) 8816013a30bd39550decc2546a47e5168e57bfcfde8plougher unlink(pathname); 8826013a30bd39550decc2546a47e5168e57bfcfde8plougher 8836f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(link(created_inode[i->inode_number - 1], pathname) == -1) { 884d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create hardlink, because " 885d4204758f77acb5a371fa1487a755b76a05d5476plougher "%s\n", strerror(errno)); 886443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 887443c15812032991c98b33b5424b17bcd55fe3575plougher } 888443c15812032991c98b33b5424b17bcd55fe3575plougher 889443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 890443c15812032991c98b33b5424b17bcd55fe3575plougher } 891443c15812032991c98b33b5424b17bcd55fe3575plougher 8926f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher switch(i->type) { 8936f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_FILE_TYPE: 8946f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_LREG_TYPE: 895d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: regular file, file_size %lld, blocks " 896d4204758f77acb5a371fa1487a755b76a05d5476plougher "%d\n", i->data, i->blocks); 897443c15812032991c98b33b5424b17bcd55fe3575plougher 89879df93becb68081effabebba3006c794be308598plougher if(write_file(i, pathname)) 899443c15812032991c98b33b5424b17bcd55fe3575plougher file_count ++; 900443c15812032991c98b33b5424b17bcd55fe3575plougher break; 9016f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher case SQUASHFS_SYMLINK_TYPE: 902d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("create_inode: symlink, symlink_size %lld\n", 903d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data); 904443c15812032991c98b33b5424b17bcd55fe3575plougher 905a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 906a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 907a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 9086f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(symlink(i->symlink, pathname) == -1) { 909d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create symlink %s, " 910d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, strerror(errno)); 911443c15812032991c98b33b5424b17bcd55fe3575plougher break; 912443c15812032991c98b33b5424b17bcd55fe3575plougher } 913443c15812032991c98b33b5424b17bcd55fe3575plougher 9149dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 9156f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lchown(pathname, i->uid, i->gid) == -1) 916d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to change uid " 917d4204758f77acb5a371fa1487a755b76a05d5476plougher "and gids on %s, because %s\n", 918d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 919443c15812032991c98b33b5424b17bcd55fe3575plougher } 920443c15812032991c98b33b5424b17bcd55fe3575plougher 921443c15812032991c98b33b5424b17bcd55fe3575plougher sym_count ++; 922443c15812032991c98b33b5424b17bcd55fe3575plougher break; 923443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_BLKDEV_TYPE: 924443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_CHRDEV_TYPE: { 9256f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; 926545404219cdd79c1e06ac7d0698d02a15240c4c3plougher TRACE("create_inode: dev, rdev 0x%llx\n", i->data); 927443c15812032991c98b33b5424b17bcd55fe3575plougher 9289dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(root_process) { 929a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 930a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 931a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 9326f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, 933d4204758f77acb5a371fa1487a755b76a05d5476plougher makedev((i->data >> 8) & 0xff, 934d4204758f77acb5a371fa1487a755b76a05d5476plougher i->data & 0xff)) == -1) { 935d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create %s " 936d4204758f77acb5a371fa1487a755b76a05d5476plougher "device %s, because %s\n", 937d4204758f77acb5a371fa1487a755b76a05d5476plougher chrdev ? "character" : "block", 938d4204758f77acb5a371fa1487a755b76a05d5476plougher pathname, strerror(errno)); 939443c15812032991c98b33b5424b17bcd55fe3575plougher break; 940443c15812032991c98b33b5424b17bcd55fe3575plougher } 941d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(pathname, i->mode, i->uid, i->gid, 942d4204758f77acb5a371fa1487a755b76a05d5476plougher i->time, TRUE); 943443c15812032991c98b33b5424b17bcd55fe3575plougher dev_count ++; 944443c15812032991c98b33b5424b17bcd55fe3575plougher } else 945d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: could not create %s device " 946d4204758f77acb5a371fa1487a755b76a05d5476plougher "%s, because you're not superuser!\n", 947545404219cdd79c1e06ac7d0698d02a15240c4c3plougher chrdev ? "character" : "block", pathname); 948443c15812032991c98b33b5424b17bcd55fe3575plougher break; 9496f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 950443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_FIFO_TYPE: 951443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: fifo\n"); 952443c15812032991c98b33b5424b17bcd55fe3575plougher 953a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher if(force) 954a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher unlink(pathname); 955a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher 956443c15812032991c98b33b5424b17bcd55fe3575plougher if(mknod(pathname, S_IFIFO, 0) == -1) { 957d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("create_inode: failed to create fifo %s, " 958d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", pathname, 959d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 960443c15812032991c98b33b5424b17bcd55fe3575plougher break; 961443c15812032991c98b33b5424b17bcd55fe3575plougher } 9626f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); 963443c15812032991c98b33b5424b17bcd55fe3575plougher fifo_count ++; 964443c15812032991c98b33b5424b17bcd55fe3575plougher break; 965443c15812032991c98b33b5424b17bcd55fe3575plougher case SQUASHFS_SOCKET_TYPE: 966443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("create_inode: socket\n"); 967443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("create_inode: socket %s ignored\n", pathname); 968443c15812032991c98b33b5424b17bcd55fe3575plougher break; 969443c15812032991c98b33b5424b17bcd55fe3575plougher default: 970d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Unknown inode type %d in create_inode_table!\n", 971d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type); 972443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 973443c15812032991c98b33b5424b17bcd55fe3575plougher } 974fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 9756f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher created_inode[i->inode_number - 1] = strdup(pathname); 976443c15812032991c98b33b5424b17bcd55fe3575plougher 977443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 978443c15812032991c98b33b5424b17bcd55fe3575plougher} 979443c15812032991c98b33b5424b17bcd55fe3575plougher 980443c15812032991c98b33b5424b17bcd55fe3575plougher 98102bc3bcabf2b219f63961f07293b83629948f026ploughervoid uncompress_directory_table(long long start, long long end) 982443c15812032991c98b33b5424b17bcd55fe3575plougher{ 983443c15812032991c98b33b5424b17bcd55fe3575plougher int bytes = 0, size = 0, res; 984443c15812032991c98b33b5424b17bcd55fe3575plougher 98541da3230b2ac91a73f9190676f66b3d80b21c270plougher TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); 98641da3230b2ac91a73f9190676f66b3d80b21c270plougher 987443c15812032991c98b33b5424b17bcd55fe3575plougher while(start < end) { 9889dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = 9899dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher realloc(directory_table, size += 9909dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher SQUASHFS_METADATA_SIZE)) == NULL) 991d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_directory_table: out of memory " 992d4204758f77acb5a371fa1487a755b76a05d5476plougher "in realloc\n"); 993443c15812032991c98b33b5424b17bcd55fe3575plougher TRACE("uncompress_directory_table: reading block 0x%llx\n", start); 994443c15812032991c98b33b5424b17bcd55fe3575plougher add_entry(directory_table_hash, start, bytes); 99502bc3bcabf2b219f63961f07293b83629948f026plougher if((res = read_block(start, &start, directory_table + bytes)) == 0) 996d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("uncompress_directory_table: failed to read " 997d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 998443c15812032991c98b33b5424b17bcd55fe3575plougher bytes += res; 999443c15812032991c98b33b5424b17bcd55fe3575plougher } 1000443c15812032991c98b33b5424b17bcd55fe3575plougher} 1001443c15812032991c98b33b5424b17bcd55fe3575plougher 1002443c15812032991c98b33b5424b17bcd55fe3575plougher 10039dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, 10049dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougherunsigned int *offset, unsigned int *type) 1005443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1006443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir->cur_entry == dir->dir_count) 1007443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1008443c15812032991c98b33b5424b17bcd55fe3575plougher 1009443c15812032991c98b33b5424b17bcd55fe3575plougher *name = dir->dirs[dir->cur_entry].name; 1010443c15812032991c98b33b5424b17bcd55fe3575plougher *start_block = dir->dirs[dir->cur_entry].start_block; 1011443c15812032991c98b33b5424b17bcd55fe3575plougher *offset = dir->dirs[dir->cur_entry].offset; 1012443c15812032991c98b33b5424b17bcd55fe3575plougher *type = dir->dirs[dir->cur_entry].type; 1013443c15812032991c98b33b5424b17bcd55fe3575plougher dir->cur_entry ++; 1014443c15812032991c98b33b5424b17bcd55fe3575plougher 1015443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1016443c15812032991c98b33b5424b17bcd55fe3575plougher} 1017443c15812032991c98b33b5424b17bcd55fe3575plougher 1018443c15812032991c98b33b5424b17bcd55fe3575plougher 1019443c15812032991c98b33b5424b17bcd55fe3575ploughervoid squashfs_closedir(struct dir *dir) 1020443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1021443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir->dirs); 1022443c15812032991c98b33b5424b17bcd55fe3575plougher free(dir); 1023443c15812032991c98b33b5424b17bcd55fe3575plougher} 1024443c15812032991c98b33b5424b17bcd55fe3575plougher 1025443c15812032991c98b33b5424b17bcd55fe3575plougher 1026b54566f5c433764830c29c83151691d0034de094plougherchar *get_component(char *target, char *targname) 1027b54566f5c433764830c29c83151691d0034de094plougher{ 1028b54566f5c433764830c29c83151691d0034de094plougher while(*target == '/') 10293cef656655723444fb1e2de1a001e6c2a54cf81erlougher target ++; 1030b54566f5c433764830c29c83151691d0034de094plougher 1031b54566f5c433764830c29c83151691d0034de094plougher while(*target != '/' && *target!= '\0') 1032b54566f5c433764830c29c83151691d0034de094plougher *targname ++ = *target ++; 1033b54566f5c433764830c29c83151691d0034de094plougher 1034b54566f5c433764830c29c83151691d0034de094plougher *targname = '\0'; 1035b54566f5c433764830c29c83151691d0034de094plougher 1036b54566f5c433764830c29c83151691d0034de094plougher return target; 1037b54566f5c433764830c29c83151691d0034de094plougher} 1038b54566f5c433764830c29c83151691d0034de094plougher 1039b54566f5c433764830c29c83151691d0034de094plougher 10406ee88c6b5da9f7b3ea88ab7481db126efa01c8f4ploughervoid free_path(struct pathname *paths) 10416ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher{ 10426ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher int i; 10436ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10446ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher for(i = 0; i < paths->names; i++) { 10456ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths) 10466ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 10476ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].name); 10486ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].preg) { 10496ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher regfree(paths->name[i].preg); 10506ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths->name[i].preg); 10516ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 10526ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } 10536ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10546ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free(paths); 10556ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher} 10566ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10576ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 10584dba330d7b952f2f044d38e342e2ae3ea78910d6plougherstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) 1059b54566f5c433764830c29c83151691d0034de094plougher{ 106071add234b27054974d5e29f95b3fab3072792a62plougher char targname[1024]; 10614dba330d7b952f2f044d38e342e2ae3ea78910d6plougher int i, error; 106271add234b27054974d5e29f95b3fab3072792a62plougher 106371add234b27054974d5e29f95b3fab3072792a62plougher target = get_component(target, targname); 106471add234b27054974d5e29f95b3fab3072792a62plougher 106571add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 10664dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if((paths = malloc(sizeof(struct pathname))) == NULL) 10674dba330d7b952f2f044d38e342e2ae3ea78910d6plougher EXIT_UNSQUASH("failed to allocate paths\n"); 10684dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 106971add234b27054974d5e29f95b3fab3072792a62plougher paths->names = 0; 107071add234b27054974d5e29f95b3fab3072792a62plougher paths->name = NULL; 107171add234b27054974d5e29f95b3fab3072792a62plougher } 107271add234b27054974d5e29f95b3fab3072792a62plougher 107371add234b27054974d5e29f95b3fab3072792a62plougher for(i = 0; i < paths->names; i++) 107471add234b27054974d5e29f95b3fab3072792a62plougher if(strcmp(paths->name[i].name, targname) == 0) 107571add234b27054974d5e29f95b3fab3072792a62plougher break; 107671add234b27054974d5e29f95b3fab3072792a62plougher 10776ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(i == paths->names) { 1078d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1079d4204758f77acb5a371fa1487a755b76a05d5476plougher * allocate new name entry 1080d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 108171add234b27054974d5e29f95b3fab3072792a62plougher paths->names ++; 1082d4204758f77acb5a371fa1487a755b76a05d5476plougher paths->name = realloc(paths->name, (i + 1) * 1083d4204758f77acb5a371fa1487a755b76a05d5476plougher sizeof(struct path_entry)); 108471add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].name = strdup(targname); 10856ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 10864dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if(use_regex) { 10874dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = malloc(sizeof(regex_t)); 1088d4204758f77acb5a371fa1487a755b76a05d5476plougher error = regcomp(paths->name[i].preg, targname, 1089d4204758f77acb5a371fa1487a755b76a05d5476plougher REG_EXTENDED|REG_NOSUB); 1090545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(error) { 10914dba330d7b952f2f044d38e342e2ae3ea78910d6plougher char str[1024]; 10924dba330d7b952f2f044d38e342e2ae3ea78910d6plougher 10934dba330d7b952f2f044d38e342e2ae3ea78910d6plougher regerror(error, paths->name[i].preg, str, 1024); 1094d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("invalid regex %s in export %s, " 1095d4204758f77acb5a371fa1487a755b76a05d5476plougher "because %s\n", targname, alltarget, str); 10964dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } 10974dba330d7b952f2f044d38e342e2ae3ea78910d6plougher } else 10984dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].preg = NULL; 10996ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11006ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(target[0] == '\0') 1101d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1102d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component 1103d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 110471add234b27054974d5e29f95b3fab3072792a62plougher paths->name[i].paths = NULL; 110571add234b27054974d5e29f95b3fab3072792a62plougher else 1106d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1107d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1108d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11094dba330d7b952f2f044d38e342e2ae3ea78910d6plougher paths->name[i].paths = add_path(NULL, target, alltarget); 11106ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else { 1111d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1112d4204758f77acb5a371fa1487a755b76a05d5476plougher * existing matching entry 1113d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11146ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher if(paths->name[i].paths == NULL) { 1115d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1116d4204758f77acb5a371fa1487a755b76a05d5476plougher * No sub-directory which means this is the leaf component 1117d4204758f77acb5a371fa1487a755b76a05d5476plougher * of a pre-existing extract which subsumes the extract 1118d4204758f77acb5a371fa1487a755b76a05d5476plougher * currently being added, in which case stop adding 1119d4204758f77acb5a371fa1487a755b76a05d5476plougher * components 1120d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11216ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else if(target[0] == '\0') { 1122d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1123d4204758f77acb5a371fa1487a755b76a05d5476plougher * at leaf pathname component and child components exist 1124d4204758f77acb5a371fa1487a755b76a05d5476plougher * from more specific extracts, delete as they're subsumed 1125d4204758f77acb5a371fa1487a755b76a05d5476plougher * by this extract 1126d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11276ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher free_path(paths->name[i].paths); 11286ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher paths->name[i].paths = NULL; 11296ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher } else 1130d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1131d4204758f77acb5a371fa1487a755b76a05d5476plougher * recurse adding child components 1132d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 11336ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher add_path(paths->name[i].paths, target, alltarget); 113471add234b27054974d5e29f95b3fab3072792a62plougher } 113571add234b27054974d5e29f95b3fab3072792a62plougher 113671add234b27054974d5e29f95b3fab3072792a62plougher return paths; 113771add234b27054974d5e29f95b3fab3072792a62plougher} 11386ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 11396ee88c6b5da9f7b3ea88ab7481db126efa01c8f4plougher 1140a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *init_subdir() 114171add234b27054974d5e29f95b3fab3072792a62plougher{ 11428372232d2460411adaa2299c32a0a88665e44902plougher struct pathnames *new = malloc(sizeof(struct pathnames)); 1143a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher new->count = 0; 1144a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return new; 1145a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1146a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1147a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1148a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) 1149a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1150a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(paths->count % PATHS_ALLOC_SIZE == 0) 1151d4204758f77acb5a371fa1487a755b76a05d5476plougher paths = realloc(paths, sizeof(struct pathnames *) + 1152d4204758f77acb5a371fa1487a755b76a05d5476plougher (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); 1153a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1154a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths->path[paths->count++] = path; 1155a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return paths; 1156a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1157a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1158a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1159a706f1b6bb48f288ecaf74e218ce20504bda52c6ploughervoid free_subdir(struct pathnames *paths) 1160a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1161a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free(paths); 1162a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher} 1163a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1164a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1165a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherint matches(struct pathnames *paths, char *name, struct pathnames **new) 1166a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher{ 1167a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int i, n; 116871add234b27054974d5e29f95b3fab3072792a62plougher 116971add234b27054974d5e29f95b3fab3072792a62plougher if(paths == NULL) { 117071add234b27054974d5e29f95b3fab3072792a62plougher *new = NULL; 1171b54566f5c433764830c29c83151691d0034de094plougher return TRUE; 117271add234b27054974d5e29f95b3fab3072792a62plougher } 117371add234b27054974d5e29f95b3fab3072792a62plougher 1174a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = init_subdir(); 1175a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1176a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(n = 0; n < paths->count; n++) { 1177a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = paths->path[n]; 1178a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher for(i = 0; i < path->names; i++) { 1179a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher int match = use_regex ? 1180d4204758f77acb5a371fa1487a755b76a05d5476plougher regexec(path->name[i].preg, name, (size_t) 0, NULL, 1181d4204758f77acb5a371fa1487a755b76a05d5476plougher 0) == 0 : fnmatch(path->name[i].name, name, 1182d4204758f77acb5a371fa1487a755b76a05d5476plougher FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; 1183a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match && path->name[i].paths == NULL) 1184d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1185d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a leaf component, any subdirectories 1186d4204758f77acb5a371fa1487a755b76a05d5476plougher * will implicitly match, therefore return an empty 1187d4204758f77acb5a371fa1487a755b76a05d5476plougher * new search set 1188d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1189a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher goto empty_set; 1190a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1191a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(match) 1192d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1193d4204758f77acb5a371fa1487a755b76a05d5476plougher * match on a non-leaf component, add any 1194d4204758f77acb5a371fa1487a755b76a05d5476plougher * subdirectories to the new set of subdirectories 1195d4204758f77acb5a371fa1487a755b76a05d5476plougher * to scan for this name 1196d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1197a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = add_subdir(*new, path->name[i].paths); 1198a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1199a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1200b54566f5c433764830c29c83151691d0034de094plougher 1201a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if((*new)->count == 0) { 1202d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1203d4204758f77acb5a371fa1487a755b76a05d5476plougher * no matching names found, delete empty search set, and return 1204d4204758f77acb5a371fa1487a755b76a05d5476plougher * FALSE 1205d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1206a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1207a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1208a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return FALSE; 1209a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 1210a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1211d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1212d4204758f77acb5a371fa1487a755b76a05d5476plougher * one or more matches with sub-directories found (no leaf matches), 1213d4204758f77acb5a371fa1487a755b76a05d5476plougher * return new search set and return TRUE 1214d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1215a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1216a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1217a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherempty_set: 1218d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1219d4204758f77acb5a371fa1487a755b76a05d5476plougher * found matching leaf exclude, return empty search set and return TRUE 1220d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1221a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(*new); 1222a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher *new = NULL; 1223a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return TRUE; 1224b54566f5c433764830c29c83151691d0034de094plougher} 1225b54566f5c433764830c29c83151691d0034de094plougher 1226b54566f5c433764830c29c83151691d0034de094plougher 1227d4204758f77acb5a371fa1487a755b76a05d5476plougherint pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1228d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1229eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1230eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher unsigned int type; 1231eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char *name, pathname[1024]; 1232eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct pathnames *new; 1233eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1234eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1235eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1236eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(dir == NULL) { 1237d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", 1238d4204758f77acb5a371fa1487a755b76a05d5476plougher parent_name, start_block, offset); 1239eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return FALSE; 1240eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1241eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1242eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1243eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1244eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1245d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", 1246d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1247eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1248eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!matches(paths, name, &new)) 1249eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1250eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1251eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 1252eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1253eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(type == SQUASHFS_DIR_TYPE) 1254eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pre_scan(parent_name, start_block, offset, new); 1255eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher else if(new == NULL) { 1256d4204758f77acb5a371fa1487a755b76a05d5476plougher if(type == SQUASHFS_FILE_TYPE || 1257d4204758f77acb5a371fa1487a755b76a05d5476plougher type == SQUASHFS_LREG_TYPE) { 1258d4204758f77acb5a371fa1487a755b76a05d5476plougher if((i = s_ops.read_inode(start_block, offset)) == 1259d4204758f77acb5a371fa1487a755b76a05d5476plougher NULL) { 1260eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher ERROR("failed to read header\n"); 1261eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher continue; 1262eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1263eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(created_inode[i->inode_number - 1] == NULL) { 1264d4204758f77acb5a371fa1487a755b76a05d5476plougher created_inode[i->inode_number - 1] = 1265d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) i; 1266d4204758f77acb5a371fa1487a755b76a05d5476plougher total_blocks += (i->data + 1267d4204758f77acb5a371fa1487a755b76a05d5476plougher (block_size - 1)) >> block_log; 1268eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1269eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_files ++; 1270eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1271eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher total_inodes ++; 1272eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1273eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1274eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher free_subdir(new); 1275eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1276eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1277eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher squashfs_closedir(dir); 1278eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1279eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return TRUE; 1280eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1281eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1282eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1283d4204758f77acb5a371fa1487a755b76a05d5476plougherint dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, 1284d4204758f77acb5a371fa1487a755b76a05d5476plougher struct pathnames *paths) 1285443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1286443c15812032991c98b33b5424b17bcd55fe3575plougher unsigned int type; 1287443c15812032991c98b33b5424b17bcd55fe3575plougher char *name, pathname[1024]; 1288a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *new; 1289eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct inode *i; 1290eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); 1291443c15812032991c98b33b5424b17bcd55fe3575plougher 1292443c15812032991c98b33b5424b17bcd55fe3575plougher if(dir == NULL) { 1293d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", 1294d4204758f77acb5a371fa1487a755b76a05d5476plougher parent_name, start_block, offset); 1295443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1296443c15812032991c98b33b5424b17bcd55fe3575plougher } 1297443c15812032991c98b33b5424b17bcd55fe3575plougher 1298eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(lsonly || info) 1299eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher print_filename(parent_name, i); 1300eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1301d4204758f77acb5a371fa1487a755b76a05d5476plougher if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && 1302d4204758f77acb5a371fa1487a755b76a05d5476plougher (!force || errno != EEXIST)) { 1303d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("dir_scan: failed to open directory %s, because %s\n", 1304d4204758f77acb5a371fa1487a755b76a05d5476plougher parent_name, strerror(errno)); 1305443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1306443c15812032991c98b33b5424b17bcd55fe3575plougher } 1307443c15812032991c98b33b5424b17bcd55fe3575plougher 1308443c15812032991c98b33b5424b17bcd55fe3575plougher while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { 1309d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", 1310d4204758f77acb5a371fa1487a755b76a05d5476plougher name, start_block, offset, type); 1311b54566f5c433764830c29c83151691d0034de094plougher 131271add234b27054974d5e29f95b3fab3072792a62plougher 131371add234b27054974d5e29f95b3fab3072792a62plougher if(!matches(paths, name, &new)) 1314b54566f5c433764830c29c83151691d0034de094plougher continue; 1315b54566f5c433764830c29c83151691d0034de094plougher 1316443c15812032991c98b33b5424b17bcd55fe3575plougher strcat(strcat(strcpy(pathname, parent_name), "/"), name); 1317fe3ca0609d02d78bcd11637c1220b2ff428f466aplougher 1318443c15812032991c98b33b5424b17bcd55fe3575plougher if(type == SQUASHFS_DIR_TYPE) 131971add234b27054974d5e29f95b3fab3072792a62plougher dir_scan(pathname, start_block, offset, new); 1320a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher else if(new == NULL) { 13216f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if((i = s_ops.read_inode(start_block, offset)) == NULL) { 13226f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher ERROR("failed to read header\n"); 13236f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher continue; 13246f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 13256f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 13266f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher if(lsonly || info) 13276f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher print_filename(pathname, i); 13286f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher 1329eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(!lsonly) { 13306f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher create_inode(pathname, i); 1331eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher update_progress_bar(); 1332eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1333427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher 1334d4204758f77acb5a371fa1487a755b76a05d5476plougher if(i->type == SQUASHFS_SYMLINK_TYPE || 1335d4204758f77acb5a371fa1487a755b76a05d5476plougher i->type == SQUASHFS_LSYMLINK_TYPE) 1336427e2790c9ae74e2ff2c25e80a469cee0bbcae44plougher free(i->symlink); 13376f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher } 1338a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 1339a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher free_subdir(new); 1340443c15812032991c98b33b5424b17bcd55fe3575plougher } 1341443c15812032991c98b33b5424b17bcd55fe3575plougher 1342074d3f1129eae914655f6637773488052bf22327rlougher if(!lsonly) 1343d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(parent_name, dir->mode, dir->uid, dir->guid, 1344d4204758f77acb5a371fa1487a755b76a05d5476plougher dir->mtime, force); 1345443c15812032991c98b33b5424b17bcd55fe3575plougher 1346443c15812032991c98b33b5424b17bcd55fe3575plougher squashfs_closedir(dir); 1347443c15812032991c98b33b5424b17bcd55fe3575plougher dir_count ++; 1348443c15812032991c98b33b5424b17bcd55fe3575plougher 1349443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1350443c15812032991c98b33b5424b17bcd55fe3575plougher} 1351443c15812032991c98b33b5424b17bcd55fe3575plougher 1352443c15812032991c98b33b5424b17bcd55fe3575plougher 1353b624936abba03d38b7e9245c647339d8f6f34274ploughervoid squashfs_stat(char *source) 1354b624936abba03d38b7e9245c647339d8f6f34274plougher{ 1355b624936abba03d38b7e9245c647339d8f6f34274plougher time_t mkfs_time = (time_t) sBlk.mkfs_time; 1356b624936abba03d38b7e9245c647339d8f6f34274plougher char *mkfs_str = ctime(&mkfs_time); 1357b624936abba03d38b7e9245c647339d8f6f34274plougher 1358b624936abba03d38b7e9245c647339d8f6f34274plougher#if __BYTE_ORDER == __BIG_ENDIAN 1359d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 1360d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.s_major == 4 ? "" : swap ? "little endian " : "big endian ", 1361d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.s_major, sBlk.s_minor, source); 1362b624936abba03d38b7e9245c647339d8f6f34274plougher#else 1363d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", 1364d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.s_major == 4 ? "" : swap ? "big endian " : "little endian ", 1365d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.s_major, sBlk.s_minor, source); 1366b624936abba03d38b7e9245c647339d8f6f34274plougher#endif 1367d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Creation or last append time %s", mkfs_str ? mkfs_str : 1368d4204758f77acb5a371fa1487a755b76a05d5476plougher "failed to get time\n"); 1369d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem is %sexportable via NFS\n", 1370d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); 1371d4204758f77acb5a371fa1487a755b76a05d5476plougher 1372d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Inodes are %scompressed\n", 1373d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); 1374d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Data is %scompressed\n", 1375d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); 1376b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) 1377d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Fragments are %scompressed\n", 1378d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); 1379d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Check data is %spresent in the filesystem\n", 1380d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); 1381b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) { 1382d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Fragments are %spresent in the filesystem\n", 1383d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); 1384d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Always_use_fragments option is %sspecified\n", 1385d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); 1386b624936abba03d38b7e9245c647339d8f6f34274plougher } else 1387b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Fragments are not supported by the filesystem\n"); 1388b624936abba03d38b7e9245c647339d8f6f34274plougher 13890337de3977eec74e6a3d28e0d0863299246de8b7plougher if(sBlk.s_major > 1) 1390d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Duplicates are %sremoved\n", 1391d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); 13920337de3977eec74e6a3d28e0d0863299246de8b7plougher else 13930337de3977eec74e6a3d28e0d0863299246de8b7plougher printf("Duplicates are removed\n"); 1394d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", 1395d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); 1396b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Block size %d\n", sBlk.block_size); 1397b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) 1398b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of fragments %d\n", sBlk.fragments); 1399b624936abba03d38b7e9245c647339d8f6f34274plougher printf("Number of inodes %d\n", sBlk.inodes); 14000f74340e3b68533339adc60f418ddf59fa188f61plougher if(sBlk.s_major == 4) 14010f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of ids %d\n", sBlk.no_ids); 14020f74340e3b68533339adc60f418ddf59fa188f61plougher else { 14030f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of uids %d\n", sBlk.no_uids); 14040f74340e3b68533339adc60f418ddf59fa188f61plougher printf("Number of gids %d\n", sBlk.no_guids); 14050f74340e3b68533339adc60f418ddf59fa188f61plougher } 1406b624936abba03d38b7e9245c647339d8f6f34274plougher 1407b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); 1408b624936abba03d38b7e9245c647339d8f6f34274plougher TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); 14090f74340e3b68533339adc60f418ddf59fa188f61plougher if(sBlk.s_major == 4) 14100f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.id_table_start 0x%llx\n", sBlk.id_table_start); 14110f74340e3b68533339adc60f418ddf59fa188f61plougher else { 14120f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); 14130f74340e3b68533339adc60f418ddf59fa188f61plougher TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); 14140f74340e3b68533339adc60f418ddf59fa188f61plougher } 1415b624936abba03d38b7e9245c647339d8f6f34274plougher if(sBlk.s_major > 1) 1416d4204758f77acb5a371fa1487a755b76a05d5476plougher TRACE("sBlk.fragment_table_start 0x%llx\n\n", 1417d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.fragment_table_start); 1418b624936abba03d38b7e9245c647339d8f6f34274plougher} 1419b624936abba03d38b7e9245c647339d8f6f34274plougher 1420b624936abba03d38b7e9245c647339d8f6f34274plougher 142102bc3bcabf2b219f63961f07293b83629948f026plougherint read_super(char *source) 1422443c15812032991c98b33b5424b17bcd55fe3575plougher{ 14236490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block_3 sBlk_3; 14246490378e5b5e8dc058daf28423a7465699a6ba7bplougher squashfs_super_block sBlk_4; 14256490378e5b5e8dc058daf28423a7465699a6ba7bplougher 14266490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 14276490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Try to read a Squashfs 4 superblock 14286490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 1429d4204758f77acb5a371fa1487a755b76a05d5476plougher read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), 1430d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) &sBlk_4); 143154660e177ba40ab08ee2f3304b9f030eb5675677plougher swap = sBlk_4.s_magic != SQUASHFS_MAGIC; 14326490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); 14336490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1434d4204758f77acb5a371fa1487a755b76a05d5476plougher if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && 1435d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk_4.s_minor == 0) { 14366490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.squashfs_opendir = squashfs_opendir_4; 14376490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment = read_fragment_4; 14386490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_fragment_table = read_fragment_table_4; 14396490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_block_list = read_block_list_2; 14406490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_inode = read_inode_4; 14416490378e5b5e8dc058daf28423a7465699a6ba7bplougher s_ops.read_uids_guids = read_uids_guids_4; 14426490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); 14436490378e5b5e8dc058daf28423a7465699a6ba7bplougher return TRUE; 14446490378e5b5e8dc058daf28423a7465699a6ba7bplougher } 14456490378e5b5e8dc058daf28423a7465699a6ba7bplougher 14466490378e5b5e8dc058daf28423a7465699a6ba7bplougher /* 14476490378e5b5e8dc058daf28423a7465699a6ba7bplougher * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock 14486490378e5b5e8dc058daf28423a7465699a6ba7bplougher * (compatible with 1 and 2 filesystems) 14496490378e5b5e8dc058daf28423a7465699a6ba7bplougher */ 1450d4204758f77acb5a371fa1487a755b76a05d5476plougher read_bytes(SQUASHFS_START, sizeof(squashfs_super_block_3), 1451d4204758f77acb5a371fa1487a755b76a05d5476plougher (char *) &sBlk_3); 1452443c15812032991c98b33b5424b17bcd55fe3575plougher 1453d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1454d4204758f77acb5a371fa1487a755b76a05d5476plougher * Check it is a SQUASHFS superblock 1455d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1456443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 0; 145721ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic != SQUASHFS_MAGIC) { 145821ee4773956342a8a7d0f14e430ae77ffbd10601plougher if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { 14597a5df5d70c02bdb5175a5b9301c2c9597a6a4937plougher squashfs_super_block_3 sblk; 1460d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Reading a different endian SQUASHFS filesystem on " 1461d4204758f77acb5a371fa1487a755b76a05d5476plougher "%s\n", source); 14626490378e5b5e8dc058daf28423a7465699a6ba7bplougher SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); 14636490378e5b5e8dc058daf28423a7465699a6ba7bplougher memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); 1464443c15812032991c98b33b5424b17bcd55fe3575plougher swap = 1; 1465443c15812032991c98b33b5424b17bcd55fe3575plougher } else { 1466443c15812032991c98b33b5424b17bcd55fe3575plougher ERROR("Can't find a SQUASHFS superblock on %s\n", source); 1467443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1468443c15812032991c98b33b5424b17bcd55fe3575plougher } 1469443c15812032991c98b33b5424b17bcd55fe3575plougher } 1470443c15812032991c98b33b5424b17bcd55fe3575plougher 14716490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.s_magic = sBlk_3.s_magic; 14726490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.inodes = sBlk_3.inodes; 14736490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.mkfs_time = sBlk_3.mkfs_time; 14746490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.block_size = sBlk_3.block_size; 14756490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.fragments = sBlk_3.fragments; 14766490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.block_log = sBlk_3.block_log; 14776490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.flags = sBlk_3.flags; 14786490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.s_major = sBlk_3.s_major; 14796490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.s_minor = sBlk_3.s_minor; 14806490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.root_inode = sBlk_3.root_inode; 14816490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.bytes_used = sBlk_3.bytes_used; 14826490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.inode_table_start = sBlk_3.inode_table_start; 14836490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.directory_table_start = sBlk_3.directory_table_start; 14846490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.fragment_table_start = sBlk_3.fragment_table_start; 14856490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.lookup_table_start = sBlk_3.lookup_table_start; 14866490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_uids = sBlk_3.no_uids; 14876490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.no_guids = sBlk_3.no_guids; 14886490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start; 14896490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start; 14906490378e5b5e8dc058daf28423a7465699a6ba7bplougher 1491443c15812032991c98b33b5424b17bcd55fe3575plougher /* Check the MAJOR & MINOR versions */ 1492ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(sBlk.s_major == 1 || sBlk.s_major == 2) { 14936490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.bytes_used = sBlk_3.bytes_used_2; 14946490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.uid_start = sBlk_3.uid_start_2; 14956490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.guid_start = sBlk_3.guid_start_2; 14966490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.inode_table_start = sBlk_3.inode_table_start_2; 14976490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.directory_table_start = sBlk_3.directory_table_start_2; 149802bc3bcabf2b219f63961f07293b83629948f026plougher 1499ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher if(sBlk.s_major == 1) { 15006490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.block_size = sBlk_3.block_size_1; 15015ff400bfbae6bb397cf3110190e83a29725fcd07plougher sBlk.fragment_table_start = sBlk.uid_start; 1502ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1503ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_1; 1504ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_block_list = read_block_list_1; 15056f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_1; 150679e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1507ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } else { 15086490378e5b5e8dc058daf28423a7465699a6ba7bplougher sBlk.fragment_table_start = sBlk_3.fragment_table_start_2; 1509ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_1; 1510ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment = read_fragment_2; 1511ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher s_ops.read_fragment_table = read_fragment_table_2; 1512ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 15136f59236ae37e220ca132b18d58f78ef1f5a1d4fbplougher s_ops.read_inode = read_inode_2; 151479e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 1515ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher } 15164ce87501a1b07102cef9750060d9a53cd5b00a61plougher } else if(sBlk.s_major == 3) { 1517ed5124f016834932db2c63d60d259d846171c216plougher s_ops.squashfs_opendir = squashfs_opendir_3; 1518ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment = read_fragment_3; 1519ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_fragment_table = read_fragment_table_3; 1520ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_block_list = read_block_list_2; 1521ed5124f016834932db2c63d60d259d846171c216plougher s_ops.read_inode = read_inode_3; 152279e700efc62527661ce140bd1013a2b60577917eplougher s_ops.read_uids_guids = read_uids_guids_1; 152302bc3bcabf2b219f63961f07293b83629948f026plougher } else { 1524d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, 1525d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.s_minor); 15264c99cb7f458d8e1c598f1c80793daf3696c9b528plougher ERROR("which is a later filesystem version than I support!\n"); 1527443c15812032991c98b33b5424b17bcd55fe3575plougher goto failed_mount; 1528443c15812032991c98b33b5424b17bcd55fe3575plougher } 1529443c15812032991c98b33b5424b17bcd55fe3575plougher 1530443c15812032991c98b33b5424b17bcd55fe3575plougher return TRUE; 1531443c15812032991c98b33b5424b17bcd55fe3575plougher 1532443c15812032991c98b33b5424b17bcd55fe3575plougherfailed_mount: 1533443c15812032991c98b33b5424b17bcd55fe3575plougher return FALSE; 1534443c15812032991c98b33b5424b17bcd55fe3575plougher} 1535443c15812032991c98b33b5424b17bcd55fe3575plougher 1536443c15812032991c98b33b5424b17bcd55fe3575plougher 1537a706f1b6bb48f288ecaf74e218ce20504bda52c6plougherstruct pathname *process_extract_files(struct pathname *path, char *filename) 153871add234b27054974d5e29f95b3fab3072792a62plougher{ 153971add234b27054974d5e29f95b3fab3072792a62plougher FILE *fd; 154071add234b27054974d5e29f95b3fab3072792a62plougher char name[16384]; 154171add234b27054974d5e29f95b3fab3072792a62plougher 15424dba330d7b952f2f044d38e342e2ae3ea78910d6plougher if((fd = fopen(filename, "r")) == NULL) 1543d4204758f77acb5a371fa1487a755b76a05d5476plougher EXIT_UNSQUASH("Could not open %s, because %s\n", filename, 1544d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 154571add234b27054974d5e29f95b3fab3072792a62plougher 154671add234b27054974d5e29f95b3fab3072792a62plougher while(fscanf(fd, "%16384[^\n]\n", name) != EOF) 1547a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, name, name); 154871add234b27054974d5e29f95b3fab3072792a62plougher 154971add234b27054974d5e29f95b3fab3072792a62plougher fclose(fd); 1550a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher return path; 155171add234b27054974d5e29f95b3fab3072792a62plougher} 155271add234b27054974d5e29f95b3fab3072792a62plougher 155371add234b27054974d5e29f95b3fab3072792a62plougher 1554d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1555d4204758f77acb5a371fa1487a755b76a05d5476plougher * reader thread. This thread processes read requests queued by the 1556d4204758f77acb5a371fa1487a755b76a05d5476plougher * cache_get() routine. 1557d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 15588888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *reader(void *arg) 15598888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 15608888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 15618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_reader); 15628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int res = read_bytes(entry->block, 15638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), 15648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher entry->data); 15658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 15668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) 1567d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1568d4204758f77acb5a371fa1487a755b76a05d5476plougher * queue successfully read block to the deflate thread(s) 1569d4204758f77acb5a371fa1487a755b76a05d5476plougher * for further processing 1570d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 15718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_deflate, entry); 15728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1573d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1574d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has either been successfully read and is 1575d4204758f77acb5a371fa1487a755b76a05d5476plougher * uncompressed, or an error has occurred, clear pending 1576d4204758f77acb5a371fa1487a755b76a05d5476plougher * flag, set error appropriately, and wake up any threads 1577d4204758f77acb5a371fa1487a755b76a05d5476plougher * waiting on this buffer 1578d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 15798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, !res); 15808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 15818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 15828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 15838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1584d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1585d4204758f77acb5a371fa1487a755b76a05d5476plougher * writer thread. This processes file write requests queued by the 1586d4204758f77acb5a371fa1487a755b76a05d5476plougher * write_file() routine. 1587d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 15888888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *writer(void *arg) 15898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 15908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 15918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 15928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 15938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct squashfs_file *file = queue_get(to_writer); 15948888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int file_fd; 15958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int hole = 0; 159627636cb2cec37a68313f9eb825c0548245eecad0plougher int failed = FALSE; 1597c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher int error; 15988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 15998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(file == NULL) { 16008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(from_writer, NULL); 16018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 16028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher TRACE("writer: regular file, blocks %d\n", file->blocks); 16058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher file_fd = file->fd; 16078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1608eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher for(i = 0; i < file->blocks; i++, cur_blocks ++) { 16098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct file_entry *block = queue_get(to_writer); 16108888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(block->buffer == 0) { /* sparse file */ 16128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole += block->size; 16138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 16148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher continue; 16158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_wait(block->buffer); 161827636cb2cec37a68313f9eb825c0548245eecad0plougher 161927636cb2cec37a68313f9eb825c0548245eecad0plougher if(block->buffer->error) 162027636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 162127636cb2cec37a68313f9eb825c0548245eecad0plougher 1622c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(failed) 1623c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher continue; 1624c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1625c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher error = write_block(file_fd, block->buffer->data + 1626c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher block->offset, block->size, hole, file->sparse); 1627c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 1628c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher if(error == FALSE) { 1629d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write data block %d\n", 1630d4204758f77acb5a371fa1487a755b76a05d5476plougher i); 163127636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 16328888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 1633c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher 16348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole = 0; 16358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_put(block->buffer); 16368888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(block); 16378888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16388888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 163927636cb2cec37a68313f9eb825c0548245eecad0plougher if(hole && failed == FALSE) { 1640d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1641d4204758f77acb5a371fa1487a755b76a05d5476plougher * corner case for hole extending to end of file 1642d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 1643d4204758f77acb5a371fa1487a755b76a05d5476plougher if(file->sparse == FALSE || 1644d4204758f77acb5a371fa1487a755b76a05d5476plougher lseek(file_fd, hole, SEEK_CUR) == -1) { 1645d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1646d4204758f77acb5a371fa1487a755b76a05d5476plougher * for files which we don't want to write 1647c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * sparsely, or for broken lseeks which cannot 1648c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * seek beyond end of file, write_block will do 1649c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher * the right thing 1650c6e684fd0562ef5339ea2c0b3ce09aa6149708cdplougher */ 16518888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher hole --; 1652d4204758f77acb5a371fa1487a755b76a05d5476plougher if(write_block(file_fd, "\0", 1, hole, 1653d4204758f77acb5a371fa1487a755b76a05d5476plougher file->sparse) == FALSE) { 1654d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse " 1655d4204758f77acb5a371fa1487a755b76a05d5476plougher "data block\n"); 165627636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 16578888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16588888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else if(ftruncate(file_fd, file->file_size) == -1) { 1659d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("writer: failed to write sparse data " 1660d4204758f77acb5a371fa1487a755b76a05d5476plougher "block\n"); 166127636cb2cec37a68313f9eb825c0548245eecad0plougher failed = TRUE; 16628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher close(file_fd); 166627636cb2cec37a68313f9eb825c0548245eecad0plougher if(failed == FALSE) 1667d4204758f77acb5a371fa1487a755b76a05d5476plougher set_attributes(file->pathname, file->mode, file->uid, 1668d4204758f77acb5a371fa1487a755b76a05d5476plougher file->gid, file->time, force); 166927636cb2cec37a68313f9eb825c0548245eecad0plougher else { 167027636cb2cec37a68313f9eb825c0548245eecad0plougher ERROR("Failed to write %s, skipping\n", file->pathname); 167127636cb2cec37a68313f9eb825c0548245eecad0plougher unlink(file->pathname); 167227636cb2cec37a68313f9eb825c0548245eecad0plougher } 167379df93becb68081effabebba3006c794be308598plougher free(file->pathname); 16748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher free(file); 167527636cb2cec37a68313f9eb825c0548245eecad0plougher 16768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 16778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 16788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1680d4204758f77acb5a371fa1487a755b76a05d5476plougher/* 1681d4204758f77acb5a371fa1487a755b76a05d5476plougher * decompress thread. This decompresses buffers queued by the read thread 1682d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 16838888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid *deflator(void *arg) 16848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 16858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher char tmp[block_size]; 16868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher while(1) { 16888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher struct cache_entry *entry = queue_get(to_deflate); 16898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int res; 16908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher unsigned long bytes = block_size; 16918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1692d4204758f77acb5a371fa1487a755b76a05d5476plougher res = uncompress((unsigned char *) tmp, &bytes, 1693d4204758f77acb5a371fa1487a755b76a05d5476plougher (const unsigned char *) entry->data, 1694d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); 16958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 16968888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res != Z_OK) { 16978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(res == Z_MEM_ERROR) 1698d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough memory" 1699d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 17008888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else if(res == Z_BUF_ERROR) 1701d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, not enough room " 1702d4204758f77acb5a371fa1487a755b76a05d5476plougher "in output buffer\n"); 17038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher else 1704d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("zlib::uncompress failed, unknown error " 1705d4204758f77acb5a371fa1487a755b76a05d5476plougher "%d\n", res); 17068888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } else 17078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher memcpy(entry->data, tmp, bytes); 17088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1709d4204758f77acb5a371fa1487a755b76a05d5476plougher /* 1710d4204758f77acb5a371fa1487a755b76a05d5476plougher * block has been either successfully decompressed, or an error 17118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher * occurred, clear pending flag, set error appropriately and 1712d4204758f77acb5a371fa1487a755b76a05d5476plougher * wake up any threads waiting on this block 1713d4204758f77acb5a371fa1487a755b76a05d5476plougher */ 17148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher cache_block_ready(entry, res != Z_OK); 17158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 17178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1719eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid *progress_thread(void *arg) 1720eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1721eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timeval timeval; 1722eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct timespec timespec; 17231b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct itimerval itimerval; 17241b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher struct winsize winsize; 17251b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 17261b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { 172701b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher if(isatty(STDOUT_FILENO)) 172801b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " 172901b4328a47a3c1ecd9ccc3ff6cde37ea973bb3c6plougher "columns\n"); 17301b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = 80; 17311b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher } else 17321b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher columns = winsize.ws_col; 17331b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGWINCH, sigwinch_handler); 17341b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher signal(SIGALRM, sigalrm_handler); 17351b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher 17361b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_sec = 0; 17371b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_value.tv_usec = 250000; 17381b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_sec = 0; 17391b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher itimerval.it_interval.tv_usec = 250000; 17401b5f6c5145f284683a2628b73ab5f8a0e37dd7b4plougher setitimer(ITIMER_REAL, &itimerval, NULL); 1741eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1742eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_init(&progress_wait, NULL); 1743eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 17441b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 1745eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(1) { 1746eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher gettimeofday(&timeval, NULL); 1747eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec = timeval.tv_sec; 1748eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if(timeval.tv_usec + 250000 > 999999) 1749eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_sec++; 1750eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; 17511b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); 17521b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress_enabled) 17531b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_bar(sym_count + dev_count + 1754d4204758f77acb5a371fa1487a755b76a05d5476plougher fifo_count + cur_blocks, total_inodes - 1755d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks, columns); 1756eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher } 1757eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1758eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1759eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 17608888b61f8ff4680247d10f7e5beb2ff35e8c867dploughervoid initialise_threads(int fragment_buffer_size, int data_buffer_size) 17618888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher{ 17628888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int i; 17638888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigset_t sigmask, old_mask; 17648888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int all_buffers_size = fragment_buffer_size + data_buffer_size; 17658888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17668888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigemptyset(&sigmask); 17678888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGINT); 17688888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher sigaddset(&sigmask, SIGQUIT); 17698888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) 17708888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); 17718888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17728888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(processors == -1) { 17738888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifndef linux 17748888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher int mib[2]; 17758888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher size_t len = sizeof(processors); 17768888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17778888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[0] = CTL_HW; 17788888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#ifdef HW_AVAILCPU 17798888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_AVAILCPU; 17808888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 17818888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher mib[1] = HW_NCPU; 17828888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 17838888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17848888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { 1785d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Failed to get number of available processors. " 1786d4204758f77acb5a371fa1487a755b76a05d5476plougher "Defaulting to 1\n"); 17878888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = 1; 17888888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17898888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#else 17908888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors = get_nprocs(); 17918888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher#endif 17928888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 17938888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 1794eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) 17958888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); 1796eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher deflator_thread = &thread[3]; 17978888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 17988888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_reader = queue_init(all_buffers_size); 17998888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher to_deflate = queue_init(all_buffers_size); 1800eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher to_writer = queue_init(1000); 18018888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher from_writer = queue_init(1); 18028888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher fragment_cache = cache_init(block_size, fragment_buffer_size); 18038888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher data_cache = cache_init(block_size, data_buffer_size); 18048888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[0], NULL, reader, NULL); 18058888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_create(&thread[1], NULL, writer, NULL); 1806eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_create(&thread[2], NULL, progress_thread, NULL); 18078888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher pthread_mutex_init(&fragment_mutex, NULL); 18088888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18098888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher for(i = 0; i < processors; i++) { 1810d4204758f77acb5a371fa1487a755b76a05d5476plougher if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) 18118888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to create thread\n"); 18128888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher } 18138888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18148888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher printf("Parallel unsquashfs: Using %d processor%s\n", processors, 18158888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher processors == 1 ? "" : "s"); 18168888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18178888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) 18188888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); 18198888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher} 18208888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18218888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 18221b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid enable_progress_bar() 18231b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 18241b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 18251b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = TRUE; 18261b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 18271b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 18281b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18291b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18301b42101056befe25b5f19d5b099e806a2ecee9cdploughervoid disable_progress_bar() 18311b42101056befe25b5f19d5b099e806a2ecee9cdplougher{ 18321b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 18331b42101056befe25b5f19d5b099e806a2ecee9cdplougher progress_enabled = FALSE; 18341b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 18351b42101056befe25b5f19d5b099e806a2ecee9cdplougher} 18361b42101056befe25b5f19d5b099e806a2ecee9cdplougher 18371b42101056befe25b5f19d5b099e806a2ecee9cdplougher 1838eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid update_progress_bar() 1839eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 18401b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_lock(&screen_mutex); 1841eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher pthread_cond_signal(&progress_wait); 18421b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_unlock(&screen_mutex); 1843eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1844eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1845eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1846eb35c81a4c4500aab9eeea2ba2271c88fe42732aploughervoid progress_bar(long long current, long long max, int columns) 1847eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher{ 1848eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher char rotate_list[] = { '|', '/', '-', '\\' }; 184984ece5dece9234d3ec58f988690c02aa41b41eb0plougher int max_digits = floor(log10(max)) + 1; 1850eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int used = max_digits * 2 + 11; 1851eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int hashes = (current * (columns - used)) / max; 1852eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher int spaces = columns - used - hashes; 1853dce832998340bea4236fddb5ba1525121044ce18plougher static int tty = -1; 1854eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1855eaf639366792995c36ae7295bddf534f6f416643plougher if((current > max) || (columns - used < 0)) 1856eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher return; 1857eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1858dce832998340bea4236fddb5ba1525121044ce18plougher if(tty == -1) 1859dce832998340bea4236fddb5ba1525121044ce18plougher tty = isatty(STDOUT_FILENO); 1860dce832998340bea4236fddb5ba1525121044ce18plougher if(!tty) { 1861dce832998340bea4236fddb5ba1525121044ce18plougher static long long previous = -1; 1862dce832998340bea4236fddb5ba1525121044ce18plougher 1863dce832998340bea4236fddb5ba1525121044ce18plougher /* Updating much more frequently than this results in huge 1864dce832998340bea4236fddb5ba1525121044ce18plougher * log files. */ 1865dce832998340bea4236fddb5ba1525121044ce18plougher if((current % 100) != 0 && current != max) 1866dce832998340bea4236fddb5ba1525121044ce18plougher return; 1867dce832998340bea4236fddb5ba1525121044ce18plougher /* Don't update just to rotate the spinner. */ 1868dce832998340bea4236fddb5ba1525121044ce18plougher if(current == previous) 1869dce832998340bea4236fddb5ba1525121044ce18plougher return; 1870dce832998340bea4236fddb5ba1525121044ce18plougher previous = current; 1871dce832998340bea4236fddb5ba1525121044ce18plougher } 1872dce832998340bea4236fddb5ba1525121044ce18plougher 1873eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("\r["); 1874eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1875eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while (hashes --) 1876eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar('='); 1877eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1878eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(rotate_list[rotate]); 1879eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1880eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher while(spaces --) 1881eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher putchar(' '); 1882eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1883eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf("] %*lld/%*lld", max_digits, current, max_digits, max); 1884eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher printf(" %3lld%%", current * 100 / max); 1885eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher fflush(stdout); 1886eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher} 1887eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1888eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 1889443c15812032991c98b33b5424b17bcd55fe3575plougher#define VERSION() \ 1890513f37ed1a2bef56f1681c0e3eec8971e4f0bd65plougher printf("unsquashfs version 4.0-CVS (2009/03/29)\n");\ 1891d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\ 1892d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n\n");\ 1893443c15812032991c98b33b5424b17bcd55fe3575plougher printf("This program is free software; you can redistribute it and/or\n");\ 1894443c15812032991c98b33b5424b17bcd55fe3575plougher printf("modify it under the terms of the GNU General Public License\n");\ 1895d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("as published by the Free Software Foundation; either version 2,"\ 1896d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1897443c15812032991c98b33b5424b17bcd55fe3575plougher printf("or (at your option) any later version.\n\n");\ 1898d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("This program is distributed in the hope that it will be useful,"\ 1899d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1900d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ 1901d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1902d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ 1903d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n");\ 1904443c15812032991c98b33b5424b17bcd55fe3575plougher printf("GNU General Public License for more details.\n"); 1905443c15812032991c98b33b5424b17bcd55fe3575plougherint main(int argc, char *argv[]) 1906443c15812032991c98b33b5424b17bcd55fe3575plougher{ 1907443c15812032991c98b33b5424b17bcd55fe3575plougher char *dest = "squashfs-root"; 1908b624936abba03d38b7e9245c647339d8f6f34274plougher int i, stat_sys = FALSE, version = FALSE; 1909545404219cdd79c1e06ac7d0698d02a15240c4c3plougher int n; 1910a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathnames *paths = NULL; 1911a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher struct pathname *path = NULL; 1912ae271cc93e3684d5314bcdc45b631e497ae43166plougher int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; 1913ae271cc93e3684d5314bcdc45b631e497ae43166plougher int data_buffer_size = DATA_BUFFER_DEFAULT; 19140cf5c297bec42c7c220d2825f12f9499f2293279plougher char *b; 1915eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher struct winsize winsize; 1916443c15812032991c98b33b5424b17bcd55fe3575plougher 19171b42101056befe25b5f19d5b099e806a2ecee9cdplougher pthread_mutex_init(&screen_mutex, NULL); 1918545404219cdd79c1e06ac7d0698d02a15240c4c3plougher root_process = geteuid() == 0; 1919545404219cdd79c1e06ac7d0698d02a15240c4c3plougher if(root_process) 19209dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher umask(0); 19219dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher 1922443c15812032991c98b33b5424b17bcd55fe3575plougher for(i = 1; i < argc; i++) { 1923443c15812032991c98b33b5424b17bcd55fe3575plougher if(*argv[i] != '-') 1924443c15812032991c98b33b5424b17bcd55fe3575plougher break; 1925d4204758f77acb5a371fa1487a755b76a05d5476plougher if(strcmp(argv[i], "-version") == 0 || 1926d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-v") == 0) { 1927443c15812032991c98b33b5424b17bcd55fe3575plougher VERSION(); 1928443c15812032991c98b33b5424b17bcd55fe3575plougher version = TRUE; 1929d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-info") == 0 || 1930d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-i") == 0) 1931443c15812032991c98b33b5424b17bcd55fe3575plougher info = TRUE; 1932a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) 1933443c15812032991c98b33b5424b17bcd55fe3575plougher lsonly = TRUE; 1934d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-no-progress") == 0 || 1935d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-n") == 0) 1936296d7d8a68e33341d68f4354b5e1fe2f3aa275a6plougher progress = FALSE; 1937d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-dest") == 0 || 1938d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-d") == 0) { 193971add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 1940d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -dest missing filename\n", 1941d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 194271add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 194371add234b27054974d5e29f95b3fab3072792a62plougher } 1944443c15812032991c98b33b5424b17bcd55fe3575plougher dest = argv[i]; 1945d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-processors") == 0 || 1946d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-p") == 0) { 1947d4204758f77acb5a371fa1487a755b76a05d5476plougher if((++i == argc) || (processors = strtol(argv[i], &b, 10), 1948d4204758f77acb5a371fa1487a755b76a05d5476plougher *b != '\0')) { 1949d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors missing or invalid " 1950d4204758f77acb5a371fa1487a755b76a05d5476plougher "processor number\n", argv[0]); 19510cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 19520cf5c297bec42c7c220d2825f12f9499f2293279plougher } 19530cf5c297bec42c7c220d2825f12f9499f2293279plougher if(processors < 1) { 1954d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -processors should be 1 or larger\n", 1955d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 19560cf5c297bec42c7c220d2825f12f9499f2293279plougher exit(1); 19570cf5c297bec42c7c220d2825f12f9499f2293279plougher } 1958d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-data-queue") == 0 || 1959d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-da") == 0) { 1960d4204758f77acb5a371fa1487a755b76a05d5476plougher if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 1961d4204758f77acb5a371fa1487a755b76a05d5476plougher 10), *b != '\0')) { 1962d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue missing or invalid queue " 1963d4204758f77acb5a371fa1487a755b76a05d5476plougher "size\n", argv[0]); 1964ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 1965ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 1966ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(data_buffer_size < 1) { 1967d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -data-queue should be 1 Mbyte or " 1968d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 1969ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 1970ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 1971d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-frag-queue") == 0 || 1972d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-fr") == 0) { 1973d4204758f77acb5a371fa1487a755b76a05d5476plougher if((++i == argc) || (fragment_buffer_size = strtol(argv[i], 1974d4204758f77acb5a371fa1487a755b76a05d5476plougher &b, 10), *b != '\0')) { 1975d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue missing or invalid queue " 1976d4204758f77acb5a371fa1487a755b76a05d5476plougher "size\n", argv[0]); 1977ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 1978ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 1979ae271cc93e3684d5314bcdc45b631e497ae43166plougher if(fragment_buffer_size < 1) { 1980d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("%s: -frag-queue should be 1 Mbyte or " 1981d4204758f77acb5a371fa1487a755b76a05d5476plougher "larger\n", argv[0]); 1982ae271cc93e3684d5314bcdc45b631e497ae43166plougher exit(1); 1983ae271cc93e3684d5314bcdc45b631e497ae43166plougher } 1984d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-force") == 0 || 1985d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-f") == 0) 1986a52d4c1b3b62c5bd1c63c392a8365afcebbf5b78plougher force = TRUE; 1987d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-stat") == 0 || 1988d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-s") == 0) 1989b624936abba03d38b7e9245c647339d8f6f34274plougher stat_sys = TRUE; 1990d4204758f77acb5a371fa1487a755b76a05d5476plougher else if(strcmp(argv[i], "-lls") == 0 || 1991d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-ll") == 0) { 19929baf35a00f38816d2054deb70184943d0686d03eplougher lsonly = TRUE; 19939baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 1994d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-linfo") == 0 || 1995d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-li") == 0) { 19969baf35a00f38816d2054deb70184943d0686d03eplougher info = TRUE; 19979baf35a00f38816d2054deb70184943d0686d03eplougher short_ls = FALSE; 1998d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-ef") == 0 || 1999d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-e") == 0) { 200071add234b27054974d5e29f95b3fab3072792a62plougher if(++i == argc) { 2001d4204758f77acb5a371fa1487a755b76a05d5476plougher fprintf(stderr, "%s: -ef missing filename\n", 2002d4204758f77acb5a371fa1487a755b76a05d5476plougher argv[0]); 200371add234b27054974d5e29f95b3fab3072792a62plougher exit(1); 200471add234b27054974d5e29f95b3fab3072792a62plougher } 2005a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = process_extract_files(path, argv[i]); 2006d4204758f77acb5a371fa1487a755b76a05d5476plougher } else if(strcmp(argv[i], "-regex") == 0 || 2007d4204758f77acb5a371fa1487a755b76a05d5476plougher strcmp(argv[i], "-r") == 0) 20084dba330d7b952f2f044d38e342e2ae3ea78910d6plougher use_regex = TRUE; 20094dba330d7b952f2f044d38e342e2ae3ea78910d6plougher else 2010b624936abba03d38b7e9245c647339d8f6f34274plougher goto options; 2011443c15812032991c98b33b5424b17bcd55fe3575plougher } 2012443c15812032991c98b33b5424b17bcd55fe3575plougher 2013feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher if(lsonly || info) 2014feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher progress = FALSE; 2015feb4051fd2a6f1f5cc65df4c0e8b117800c016c9plougher 2016bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#ifdef SQUASHFS_TRACE 2017bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher progress = FALSE; 2018bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher#endif 2019bfa6e0b4ecb0e0cf3d451d1a094bc88c88593f76plougher 2020443c15812032991c98b33b5424b17bcd55fe3575plougher if(i == argc) { 2021443c15812032991c98b33b5424b17bcd55fe3575plougher if(!version) { 2022443c15812032991c98b33b5424b17bcd55fe3575plougheroptions: 2023d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("SYNTAX: %s [options] filesystem [directories or " 2024d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract]\n", argv[0]); 2025d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-v[ersion]\t\tprint version, licence and " 2026d4204758f77acb5a371fa1487a755b76a05d5476plougher "copyright information\n"); 2027d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " 2028d4204758f77acb5a371fa1487a755b76a05d5476plougher "default \"squashfs-root\"\n"); 2029d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-n[o-progress]\t\tdon't display the progress bar" 2030d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2031d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-p[rocessors] <number>\tuse <number> processors." 2032d4204758f77acb5a371fa1487a755b76a05d5476plougher " By default will use\n\t\t\t\tnumber of " 2033d4204758f77acb5a371fa1487a755b76a05d5476plougher "processors available\n"); 2034d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed" 2035d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2036d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-li[nfo]\t\tprint files as they are unsquashed " 2037d4204758f77acb5a371fa1487a755b76a05d5476plougher "with file\n\t\t\t\tattributes (like ls -l " 2038d4204758f77acb5a371fa1487a755b76a05d5476plougher "output)\n"); 2039d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" 2040d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2041d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes " 2042d4204758f77acb5a371fa1487a755b76a05d5476plougher "(like\n\t\t\t\tls -l output), but don't unsquash" 2043d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2044d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-f[orce]\t\tif file already exists then overwrite" 2045d4204758f77acb5a371fa1487a755b76a05d5476plougher "\n"); 2046d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " 2047d4204758f77acb5a371fa1487a755b76a05d5476plougher "information\n"); 2048d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-e[f] <extract file>\tlist of directories or " 2049d4204758f77acb5a371fa1487a755b76a05d5476plougher "files to extract.\n\t\t\t\tOne per line\n"); 2050d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-da[ta-queue] <size>\tSet data queue to <size> " 2051d4204758f77acb5a371fa1487a755b76a05d5476plougher "Mbytes. Default %d\n\t\t\t\tMbytes\n", 2052d4204758f77acb5a371fa1487a755b76a05d5476plougher DATA_BUFFER_DEFAULT); 2053d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to " 2054d4204758f77acb5a371fa1487a755b76a05d5476plougher "<size> Mbytes. Default %d\n\t\t\t\t Mbytes\n", 2055d4204758f77acb5a371fa1487a755b76a05d5476plougher FRAGMENT_BUFFER_DEFAULT); 2056d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular " 2057d4204758f77acb5a371fa1487a755b76a05d5476plougher "expressions\n\t\t\t\trather than use the default " 2058d4204758f77acb5a371fa1487a755b76a05d5476plougher "shell wildcard\n\t\t\t\texpansion (globbing)\n"); 2059443c15812032991c98b33b5424b17bcd55fe3575plougher } 2060443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2061443c15812032991c98b33b5424b17bcd55fe3575plougher } 2062443c15812032991c98b33b5424b17bcd55fe3575plougher 206371add234b27054974d5e29f95b3fab3072792a62plougher for(n = i + 1; n < argc; n++) 2064a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher path = add_path(path, argv[n], argv[n]); 2065b54566f5c433764830c29c83151691d0034de094plougher 2066443c15812032991c98b33b5424b17bcd55fe3575plougher if((fd = open(argv[i], O_RDONLY)) == -1) { 2067d4204758f77acb5a371fa1487a755b76a05d5476plougher ERROR("Could not open %s, because %s\n", argv[i], 2068d4204758f77acb5a371fa1487a755b76a05d5476plougher strerror(errno)); 2069443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2070443c15812032991c98b33b5424b17bcd55fe3575plougher } 2071443c15812032991c98b33b5424b17bcd55fe3575plougher 207202bc3bcabf2b219f63961f07293b83629948f026plougher if(read_super(argv[i]) == FALSE) 2073443c15812032991c98b33b5424b17bcd55fe3575plougher exit(1); 2074443c15812032991c98b33b5424b17bcd55fe3575plougher 2075b624936abba03d38b7e9245c647339d8f6f34274plougher if(stat_sys) { 2076b624936abba03d38b7e9245c647339d8f6f34274plougher squashfs_stat(argv[i]); 2077b624936abba03d38b7e9245c647339d8f6f34274plougher exit(0); 2078b624936abba03d38b7e9245c647339d8f6f34274plougher } 2079b624936abba03d38b7e9245c647339d8f6f34274plougher 2080443c15812032991c98b33b5424b17bcd55fe3575plougher block_size = sBlk.block_size; 2081ae271cc93e3684d5314bcdc45b631e497ae43166plougher block_log = sBlk.block_log; 2082ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2083ae271cc93e3684d5314bcdc45b631e497ae43166plougher fragment_buffer_size <<= 20 - block_log; 2084ae271cc93e3684d5314bcdc45b631e497ae43166plougher data_buffer_size <<= 20 - block_log; 20858888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher initialise_threads(fragment_buffer_size, data_buffer_size); 20868888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 2087443c15812032991c98b33b5424b17bcd55fe3575plougher if((fragment_data = malloc(block_size)) == NULL) 2088443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate fragment_data\n"); 2089443c15812032991c98b33b5424b17bcd55fe3575plougher 2090443c15812032991c98b33b5424b17bcd55fe3575plougher if((file_data = malloc(block_size)) == NULL) 2091443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate file_data"); 2092443c15812032991c98b33b5424b17bcd55fe3575plougher 2093443c15812032991c98b33b5424b17bcd55fe3575plougher if((data = malloc(block_size)) == NULL) 2094eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher EXIT_UNSQUASH("failed to allocate data\n"); 2095443c15812032991c98b33b5424b17bcd55fe3575plougher 2096443c15812032991c98b33b5424b17bcd55fe3575plougher if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) 2097443c15812032991c98b33b5424b17bcd55fe3575plougher EXIT_UNSQUASH("failed to allocate created_inode\n"); 2098443c15812032991c98b33b5424b17bcd55fe3575plougher 2099443c15812032991c98b33b5424b17bcd55fe3575plougher memset(created_inode, 0, sBlk.inodes * sizeof(char *)); 2100443c15812032991c98b33b5424b17bcd55fe3575plougher 21011a7e7e871169a6cb6e3470a50b33db83830886e2plougher if(s_ops.read_uids_guids() == FALSE) 21021a7e7e871169a6cb6e3470a50b33db83830886e2plougher EXIT_UNSQUASH("failed to uid/gid table\n"); 2103ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2104cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher if(s_ops.read_fragment_table() == FALSE) 2105cce13b2f8f73a4224f9dcfe203c992a09f22c6bcplougher EXIT_UNSQUASH("failed to read fragment table\n"); 2106ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2107d4204758f77acb5a371fa1487a755b76a05d5476plougher uncompress_inode_table(sBlk.inode_table_start, 2108d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.directory_table_start); 2109ba3d412c7c811a9b335a52ec497ce511e35b2bc8plougher 2110d4204758f77acb5a371fa1487a755b76a05d5476plougher uncompress_directory_table(sBlk.directory_table_start, 2111d4204758f77acb5a371fa1487a755b76a05d5476plougher sBlk.fragment_table_start); 2112443c15812032991c98b33b5424b17bcd55fe3575plougher 2113a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher if(path) { 2114a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = init_subdir(); 2115a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher paths = add_subdir(paths, path); 2116a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher } 2117a706f1b6bb48f288ecaf74e218ce20504bda52c6plougher 2118d4204758f77acb5a371fa1487a755b76a05d5476plougher pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), 2119d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); 2120eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2121eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher memset(created_inode, 0, sBlk.inodes * sizeof(char *)); 21229b58176e667b67770569c9076a410b27aaa3bcf5plougher inode_number = 1; 2123eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2124d4204758f77acb5a371fa1487a755b76a05d5476plougher printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - 2125d4204758f77acb5a371fa1487a755b76a05d5476plougher total_files + total_blocks); 2126eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 21271b42101056befe25b5f19d5b099e806a2ecee9cdplougher if(progress) 21281b42101056befe25b5f19d5b099e806a2ecee9cdplougher enable_progress_bar(); 21291b42101056befe25b5f19d5b099e806a2ecee9cdplougher 2130d4204758f77acb5a371fa1487a755b76a05d5476plougher dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), 2131d4204758f77acb5a371fa1487a755b76a05d5476plougher SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); 2132443c15812032991c98b33b5424b17bcd55fe3575plougher 21338888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_put(to_writer, NULL); 21348888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher queue_get(from_writer); 21358888b61f8ff4680247d10f7e5beb2ff35e8c867dplougher 21365c7885bc293ab675812fd77a05f59c2917e3e8b4plougher if(progress) { 21371b42101056befe25b5f19d5b099e806a2ecee9cdplougher disable_progress_bar(); 21385c7885bc293ab675812fd77a05f59c2917e3e8b4plougher progress_bar(sym_count + dev_count + fifo_count + cur_blocks, 21391b42101056befe25b5f19d5b099e806a2ecee9cdplougher total_inodes - total_files + total_blocks, columns); 21405c7885bc293ab675812fd77a05f59c2917e3e8b4plougher } 2141eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 2142443c15812032991c98b33b5424b17bcd55fe3575plougher if(!lsonly) { 2143443c15812032991c98b33b5424b17bcd55fe3575plougher printf("\n"); 2144443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d files\n", file_count); 2145443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d directories\n", dir_count); 2146443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d symlinks\n", sym_count); 2147443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d devices\n", dev_count); 2148443c15812032991c98b33b5424b17bcd55fe3575plougher printf("created %d fifos\n", fifo_count); 2149443c15812032991c98b33b5424b17bcd55fe3575plougher } 2150eb35c81a4c4500aab9eeea2ba2271c88fe42732aplougher 21519dd8c7a7c2983faeb60c5e5791c3bef2cbbba088plougher return 0; 2152443c15812032991c98b33b5424b17bcd55fe3575plougher} 2153