diff --git a/util/lar/lar.c b/util/lar/lar.c index 86a30317b7..987e954183 100644 --- a/util/lar/lar.c +++ b/util/lar/lar.c @@ -182,6 +182,39 @@ int list_lar(const char *archivename, struct file *files) return 0; } +int zerofill_lar(const char *archivename) +{ + struct lar_header *header; + int ret, hlen; + int pathlen; + u32 *walk, csum; + u32 offset; + char *name = "zerofill"; + int zerolen; + char *zero; + + struct lar *lar = lar_open_archive(archivename); + + if (lar == NULL) { + fprintf(stderr, "Unable to open LAR archive %s\n", archivename); + exit(1); + } + + zerolen = maxsize(lar, name); + if (zerolen <= 0) { + fprintf(stderr, "No room for zerofill.\n"); + return -1; + } + + zero = malloc(zerolen); + memset(zero, 0xff, zerolen); + + lar_add_entry(lar, name, zero, zerolen, zerolen,0, 0, 0); + + lar_close_archive(lar); + return 0; +} + int extract_lar(const char *archivename, struct file *files) { int ret; @@ -218,6 +251,7 @@ int main(int argc, char *argv[]) {"elfparse", 1, 0, 'e'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, + {"zerofill", 0, 0, 'z'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; @@ -227,7 +261,7 @@ int main(int argc, char *argv[]) exit(1); } - while ((opt = getopt_long(argc, argv, "acC:xels:b:vVh?", + while ((opt = getopt_long(argc, argv, "acC:xzels:b:vVh?", long_options, &option_index)) != EOF) { switch (opt) { case 'a': @@ -253,6 +287,9 @@ int main(int argc, char *argv[]) case 'x': larmode = EXTRACT; break; + case 'z': + larmode = ZEROFILL; + break; case 's': parse_larsize(optarg); break; @@ -287,6 +324,8 @@ int main(int argc, char *argv[]) larmode = CREATE; else if (strncmp(argv[optind], "l", 2) == 0) larmode = LIST; + else if (strncmp(argv[optind], "z", 2) == 0) + larmode = ZEROFILL; /* If larmode changed in this if branch, * eat a parameter @@ -324,7 +363,7 @@ int main(int argc, char *argv[]) if (optind < argc) { archivename = argv[optind++]; - } else { + } else if (larmode != ZEROFILL) { usage(argv[0]); fprintf(stderr, "Error: No archive name.\n\n"); @@ -356,6 +395,9 @@ int main(int argc, char *argv[]) case LIST: list_lar(archivename, get_files()); break; + case ZEROFILL: + zerofill_lar(archivename); + break; } free_files(); diff --git a/util/lar/lib.h b/util/lar/lib.h index 656ace9507..c59aeef2f7 100644 --- a/util/lar/lib.h +++ b/util/lar/lib.h @@ -33,7 +33,8 @@ enum { ADD, CREATE, LIST, - EXTRACT + EXTRACT, + ZEROFILL, } larmodes; /* prototypes for lar.c functions */ @@ -58,6 +59,8 @@ int iself(char *filebuf); int lar_process_name(char *name, char **pfilename, char **ppathname, enum compalgo *thisalgo); u32 lar_compress(char *ptr, ssize_t size, char *temp, enum compalgo *thisalgo); +int hlen(char *name); +int maxsize(struct lar *lar, char *name); int lar_add_entry(struct lar *lar, char *pathname, void *data, u32 complen, u32 reallen, u32 loadaddress, u32 entry, enum compalgo thisalgo); diff --git a/util/lar/stream.c b/util/lar/stream.c index f3542e79b8..e3cd86e2b0 100644 --- a/util/lar/stream.c +++ b/util/lar/stream.c @@ -783,6 +783,45 @@ char *mapfile(char *filename, u32 *size) return ptr; } +/** + * Given a name, return the size of the header for that name. + * + * @param name header name + * @return header size + */ +int hlen(char *pathname) +{ + int pathlen; + int len; + + pathlen = strlen(pathname) + 1 > MAX_PATHLEN ? + MAX_PATHLEN : strlen(pathname) + 1; + len = sizeof(struct lar_header) + pathlen; + len = (len + 15) & 0xFFFFFFF0; + + return len; +} + +/** + * Return the amount of space left in a lar, given a name for the entry + * @param Name of the entry + * @return Maximum possible size for the entry + */ +int maxsize(struct lar *lar, char *name) +{ + int size; + u32 offset; + int bootblock_size; + + /* Find the beginning of the available space in the LAR */ + offset = lar_empty_offset(lar); + + /* Figure out how big our header will be */ + size = get_bootblock_offset(lar->size) - offset - hlen(name) - 1; + + return size; +} + /** * Compress an area according to an algorithm. If the area grows, * use no compression.