diff options
author | James Cameron <quozl@laptop.org> | 2011-04-21 04:46:31 (GMT) |
---|---|---|
committer | Daniel Drake <dsd@laptop.org> | 2011-05-03 19:47:08 (GMT) |
commit | a17b54443ecceea57df5dfc05145da2d085e2fba (patch) | |
tree | 0cc34f0b5195190a6e71a31254ff7d4ad39844e1 /bin | |
parent | a208d67f5aa86f39da0bcbc25e8c635056c84ec1 (diff) |
zhashfs: detect fill pattern and suppress blocks in output
Allows the unused filesystem blocks of the image to be left out of the
.zd file, resulting in a factor of two reduction in fs-update times on
a typical build on a 4GB microSD. Greater reduction occurs on larger
microSD or SD cards.
Has no effect if a fill pattern file is not found.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/zhashfs.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/bin/zhashfs.c b/bin/zhashfs.c index 87fd2df..b3b86e0 100644 --- a/bin/zhashfs.c +++ b/bin/zhashfs.c @@ -13,6 +13,8 @@ static long zbufsize; static long zblocksize; static char *hashname; +#define PATTERN_SIZE 4096 + #define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x); } while (0); static void run_cmd(int res, int line, char *file, char *cmd) { @@ -77,7 +79,12 @@ int main(int argc, char **argv) off_t insize; int readlen; - int allf; + int skip; + + unsigned char *pbuf; // fill pattern buffer + char *pname; // fill pattern file name + FILE *pfile; // fill pattern file + int patterned, n; if (argc < 6) { fprintf(stderr, "%s: zblocksize hashname signed_file_name spec_file_name zdata_file_name [ #blocks ]\n", argv[0]); @@ -112,6 +119,18 @@ int main(int argc, char **argv) infile = fopen(argv[3], "rb"); LTC_ARGCHK(infile != NULL); + /* open and read an optional fill pattern file */ + pbuf = NULL; + pname = strcat(argv[3], ".fill"); + pfile = fopen(pname, "rb"); + if (pfile != NULL) { + pbuf = malloc(PATTERN_SIZE); + LTC_ARGCHK(pbuf != NULL); + n = fread(pbuf, 1, PATTERN_SIZE, pfile); + LTC_ARGCHK(n == PATTERN_SIZE); + fclose(pfile); + } + /* open output file */ outfile = fopen(argv[4], "wb"); LTC_ARGCHK(outfile != NULL); @@ -155,18 +174,38 @@ int main(int argc, char **argv) LTC_ARGCHK(readlen == zblocksize); #ifdef notdef - allf = 1; + skip = 1; for (p = (unsigned char *)buf; p < &buf[zblocksize]; p++) { if (*p != 0xff) { - allf = 0; + skip = 0; break; } } #else - allf = 0; + skip = 0; #endif - if (!allf) + if (pbuf) { + /* check if this zblock is fully patterned as unused, and if + any parts of the zblock are patterned then zero them, for ease + of compression */ + + patterned = 1; + for (n = 0; n < (zblocksize / PATTERN_SIZE); n++) { + if (memcmp(&buf[n*PATTERN_SIZE], pbuf, PATTERN_SIZE)) { + patterned = 0; + } else { + memset(&buf[n*PATTERN_SIZE], 0, PATTERN_SIZE); + } + } + + /* skip any block that is fully patterned, thus relying on the + fs-update card erase-blocks */ + + if (patterned) skip++; + } + + if (!skip) write_block(i, buf); fprintf(stdout, "\r%ld", i); fflush(stdout); |