diff options
author | Ian Campbell <ian.campbell@xensource.com> | 2006-10-26 16:56:16 +0100 |
---|---|---|
committer | Ian Campbell <ian.campbell@xensource.com> | 2006-10-26 16:56:16 +0100 |
commit | 1459957f98d243d64d6f1f76d2a91cd26a9d7202 (patch) | |
tree | 65ca2820cababd0c64b12e2b90b09132c2be4ecf /tools/libxc/xg_private.c | |
parent | 53132173d5bfbe48b369968bd198cbc72b3fbd2b (diff) | |
download | xen-1459957f98d243d64d6f1f76d2a91cd26a9d7202.tar.gz xen-1459957f98d243d64d6f1f76d2a91cd26a9d7202.tar.bz2 xen-1459957f98d243d64d6f1f76d2a91cd26a9d7202.zip |
[TOOLS] Uncompress and allocate memory for gzipped kernel and initrd images on
the fly. We cannot rely on the length contained in the gzip trailer to determine
the length of the decompressed data because images have been observed which have
trailing junk.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
Diffstat (limited to 'tools/libxc/xg_private.c')
-rw-r--r-- | tools/libxc/xg_private.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 86cef6efa8..3c50552290 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -31,7 +31,7 @@ char *xc_read_image(const char *filename, unsigned long *size) { int kernel_fd = -1; gzFile kernel_gfd = NULL; - char *image = NULL; + char *image = NULL, *tmp; unsigned int bytes; if ( (filename == NULL) || (size == NULL) ) @@ -43,33 +43,58 @@ char *xc_read_image(const char *filename, unsigned long *size) goto out; } - if ( (*size = xc_get_filesz(kernel_fd)) == 0 ) - { - PERROR("Could not read kernel image"); - goto out; - } - if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL ) { PERROR("Could not allocate decompression state for state file"); goto out; } - if ( (image = malloc(*size)) == NULL ) + *size = 0; + +#define CHUNK 1*1024*1024 + while(1) { - PERROR("Could not allocate memory for kernel image"); - goto out; + if ( (tmp = realloc(image, *size + CHUNK)) == NULL ) + { + PERROR("Could not allocate memory for kernel image"); + free(image); + image = NULL; + goto out; + } + image = tmp; + + bytes = gzread(kernel_gfd, image + *size, CHUNK); + switch (bytes) + { + case -1: + PERROR("Error reading kernel image"); + free(image); + image = NULL; + goto out; + case 0: /* EOF */ + goto out; + default: + *size += bytes; + break; + } } +#undef CHUNK - if ( (bytes = gzread(kernel_gfd, image, *size)) != *size ) + out: + if ( *size == 0 ) { - PERROR("Error reading kernel image, could not" - " read the whole image (%d != %ld).", bytes, *size); - free(image); - image = NULL; + PERROR("Could not read kernel image"); + free(image); + image = NULL; + } + else if ( image ) + { + /* Shrink allocation to fit image. */ + tmp = realloc(image, *size); + if ( tmp ) + image = tmp; } - out: if ( kernel_gfd != NULL ) gzclose(kernel_gfd); else if ( kernel_fd >= 0 ) |