diff options
| author | H. Peter Anvin <hpa@zytor.com> | 2008-02-27 12:40:31 -0800 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2008-02-27 12:40:31 -0800 |
| commit | 48722c47bbdcfe51e905e87ec0d34415506393c5 (patch) | |
| tree | b20c6bb0d1f556068eeb813db89892b645bec777 /com32/lib/syslinux | |
| parent | bcfd0df3c9778eff358926dffd35f870becff26b (diff) | |
| download | syslinux-48722c47bbdcfe51e905e87ec0d34415506393c5.tar.gz | |
Comboot/Com32 changes for unspecified file lengths
Handle unspecified file length for comboot/com32 modules; do changes
to the appropriate part of libcom32 to handle this properly.
Diffstat (limited to 'com32/lib/syslinux')
| -rw-r--r-- | com32/lib/syslinux/loadfile.c | 91 |
1 files changed, 65 insertions, 26 deletions
diff --git a/com32/lib/syslinux/loadfile.c b/com32/lib/syslinux/loadfile.c index ec7a6039..f5479dab 100644 --- a/com32/lib/syslinux/loadfile.c +++ b/com32/lib/syslinux/loadfile.c @@ -25,45 +25,84 @@ #include <syslinux/loadfile.h> +#define INCREMENTAL_CHUNK 1024*1024 + int loadfile(const char *filename, void **ptr, size_t *len) { - int fd; - struct stat st; - void *data; FILE *f; - size_t xlen; + int rv; - fd = open(filename, O_RDONLY); - if ( fd < 0 ) + f = fopen(filename, "r"); + if ( !f ) return -1; - f = fdopen(fd, "rb"); - if ( !f ) { - close(fd); - return -1; - } + rv = floadfile(f, ptr, len, NULL, 0); + fclose(f); - if ( fstat(fd, &st) ) - goto err_fclose; + return rv; +} - *len = st.st_size; - xlen = (st.st_size + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1); +int floadfile(FILE *f, void **ptr, size_t *len, const void *prefix, + size_t prefix_len) +{ + struct stat st; + void *data, *dp; + size_t alen, clen, rlen, xlen; - *ptr = data = malloc(xlen); - if ( !data ) - goto err_fclose; + clen = alen = 0; + data = NULL; - if ( (off_t)fread(data, 1, st.st_size, f) != st.st_size ) - goto err_free; + if ( fstat(fileno(f), &st) ) + goto err; - memset((char *)data + st.st_size, 0, xlen-st.st_size); + if (!S_ISREG(st.st_mode)) { + /* Not a regular file, we can't assume we know the file size */ + if (prefix_len) { + clen = alen = prefix_len; + data = malloc(prefix_len); + if (!data) + goto err; - fclose(f); + memcpy(data, prefix, prefix_len); + } + + do { + alen += INCREMENTAL_CHUNK; + dp = realloc(data, alen); + if (!dp) + goto err; + data = dp; + + rlen = fread((char *)data+clen, 1, alen-clen, f); + clen += rlen; + } while (clen == alen); + + *len = clen; + xlen = (clen + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1); + dp = realloc(data, xlen); + if (dp) + data = dp; + *ptr = data; + } else { + *len = clen = st.st_size + prefix_len - ftell(f); + xlen = (clen + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1); + + *ptr = data = malloc(xlen); + if ( !data ) + return -1; + + memcpy(data, prefix, prefix_len); + + if ( (off_t)fread((char *)data+prefix_len, 1, clen-prefix_len, f) + != clen-prefix_len ) + goto err; + } + + memset((char *)data + clen, 0, xlen-clen); return 0; - err_free: - free(data); - err_fclose: - fclose(f); + err: + if (data) + free(data); return -1; } |
