| From dc1463c684932fbdab47b203b67d8b6f075da254 Mon Sep 17 00:00:00 2001 |
| From: Amin Hassani <ahassani@google.com> |
| Date: Fri, 11 Aug 2017 11:20:02 -0700 |
| Subject: [PATCH 1/3] Generate squashfs image file map using unsquashfs |
| |
| This CL modifies unsquashfs to generate a file map when given the flag |
| -m or -map. The structure of the file map is a list of per-line of the |
| following: |
| |
| path start compressed_block_size_1 ... compressed_block_size_N |
| |
| where: |
| - 'path' is the full path to the file. |
| - 'start' is the start byte address of the file. |
| - 'compressed_block_size_i' is a the length of the i'th compressed block |
| in bytes. If the block is uncompressed its 25th LSB is set. |
| |
| It also first prints the list of all fragments along with their address |
| and block sizes at the beginning of the aforementioned list. The path |
| for each fragment is '<fragment_i>' with 'i' be the i'th fragment. |
| |
| The usage: |
| unsquashfs -m(ap) <path_to_file_map> <squashfs_image> |
| --- |
| squashfs-tools/unsquashfs.c | 63 ++++++++++++++++++++++++++++++++++--- |
| 1 file changed, 58 insertions(+), 5 deletions(-) |
| |
| diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c |
| index 65f208d..f82f197 100644 |
| --- a/squashfs-tools/unsquashfs.c |
| +++ b/squashfs-tools/unsquashfs.c |
| @@ -78,6 +78,9 @@ int user_xattrs = FALSE; |
| int ignore_errors = FALSE; |
| int strict_errors = FALSE; |
| int use_localtime = TRUE; |
| +int lsfilemap = FALSE; |
| +char* file_map_path = NULL; |
| +FILE* file_map_file = NULL; |
| |
| int lookup_type[] = { |
| 0, |
| @@ -498,7 +501,6 @@ void dump_cache(struct cache *cache) |
| pthread_mutex_unlock(&cache->mutex); |
| } |
| |
| - |
| char *modestr(char *str, int mode) |
| { |
| int i; |
| @@ -513,6 +515,15 @@ char *modestr(char *str, int mode) |
| return str; |
| } |
| |
| +void print_file_map(char* pathname, long long start, int block_count, |
| + unsigned int* block_list) |
| +{ |
| + fprintf(file_map_file, "%s %lld", pathname, start); |
| + int i; |
| + for(i = 0; i < block_count; i++) |
| + fprintf(file_map_file, " %u", block_list[i]); |
| + fprintf(file_map_file, "\n"); |
| +} |
| |
| #define TOTALCHARS 25 |
| int print_filename(char *pathname, struct inode *inode) |
| @@ -525,7 +536,20 @@ int print_filename(char *pathname, struct inode *inode) |
| struct tm *t; |
| |
| if(short_ls) { |
| - printf("%s\n", pathname); |
| + if(!lsfilemap) |
| + printf("%s\n", pathname); |
| + else if((SQUASHFS_FILE_TYPE == inode->type || |
| + SQUASHFS_LREG_TYPE == inode->type) && |
| + inode->fragment < 0) { |
| + unsigned int* block_list = |
| + malloc(inode->blocks * sizeof(unsigned int)); |
| + if(block_list == NULL) |
| + EXIT_UNSQUASH("print_filename: unable to malloc block list\n"); |
| + s_ops->read_block_list(block_list, inode->block_ptr, inode->blocks); |
| + print_file_map(pathname, inode->start, inode->blocks, |
| + block_list); |
| + free(block_list); |
| + } |
| return 1; |
| } |
| |
| @@ -1604,7 +1628,7 @@ int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, |
| return FALSE; |
| } |
| |
| - if((lsonly || info) && (!concise || dir->dir_count ==0)) |
| + if(!lsfilemap && (lsonly || info) && (!concise || dir->dir_count ==0)) |
| print_filename(parent_name, i); |
| |
| if(!lsonly) { |
| @@ -1668,7 +1692,7 @@ int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, |
| |
| i = s_ops->read_inode(start_block, offset); |
| |
| - if(lsonly || info) |
| + if(lsfilemap || lsonly || info) |
| print_filename(pathname, i); |
| |
| if(!lsonly) { |
| @@ -2786,6 +2810,16 @@ int main(int argc, char *argv[]) |
| ERROR("%s: %s missing or invalid offset size\n", argv[0], argv[i - 1]); |
| exit(1); |
| } |
| + } else if(strcmp(argv[i], "-map") == 0 || |
| + strcmp(argv[i], "-m") == 0) { |
| + if(++i == argc) { |
| + ERROR("%s: -map missing filename\n", |
| + argv[0]); |
| + exit(1); |
| + } |
| + file_map_path = argv[i]; |
| + lsonly = TRUE; |
| + lsfilemap = TRUE; |
| } else |
| goto options; |
| } |
| @@ -2869,6 +2903,8 @@ options: |
| "regular expressions\n"); |
| ERROR("\t\t\t\trather than use the default shell " |
| "wildcard\n\t\t\t\texpansion (globbing)\n"); |
| + ERROR("\t-m[ap] <file>\tcreates file map" |
| + ", but doesn't unsquash\n"); |
| ERROR("\nDecompressors available:\n"); |
| display_compressors("", ""); |
| } |
| @@ -2970,10 +3006,24 @@ options: |
| printf("%d inodes (%d blocks) to write\n\n", total_inodes, |
| total_inodes - total_files + total_blocks); |
| } |
| - |
| enable_progress_bar(); |
| } |
| |
| + if(lsfilemap) { |
| + int i, size; |
| + long long start; |
| + char tmp[22]; |
| + file_map_file = fopen(file_map_path, "w"); |
| + if(file_map_file == NULL) |
| + EXIT_UNSQUASH("Failed to open file map \"%s\" because %s\n", |
| + file_map_path, strerror(errno)); |
| + for(i = 0; i < sBlk.s.fragments; i++) { |
| + s_ops->read_fragment(i, &start, &size); |
| + snprintf(tmp, 22, "<fragment-%d>", i); |
| + print_file_map(tmp, start, 1, (unsigned int*)&size); |
| + } |
| + } |
| + |
| res = dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), |
| SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); |
| if(res == FALSE) |
| @@ -2984,6 +3034,9 @@ options: |
| if(res == TRUE) |
| exit_code = 1; |
| |
| + if(lsfilemap) |
| + fclose(file_map_file); |
| + |
| disable_progress_bar(); |
| |
| if(!quiet && !lsonly) { |
| -- |
| 2.31.1.527.g47e6f16901-goog |
| |