blob: 01a6374be6a584b4d0dba19abc327ec3494f813c [file] [log] [blame]
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