aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xg_private.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@xensource.com>2006-10-26 16:56:16 +0100
committerIan Campbell <ian.campbell@xensource.com>2006-10-26 16:56:16 +0100
commit1459957f98d243d64d6f1f76d2a91cd26a9d7202 (patch)
tree65ca2820cababd0c64b12e2b90b09132c2be4ecf /tools/libxc/xg_private.c
parent53132173d5bfbe48b369968bd198cbc72b3fbd2b (diff)
downloadxen-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.c57
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 )