summaryrefslogtreecommitdiff
path: root/com32/lib/syslinux
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-02-27 12:40:31 -0800
committerH. Peter Anvin <hpa@zytor.com>2008-02-27 12:40:31 -0800
commit48722c47bbdcfe51e905e87ec0d34415506393c5 (patch)
treeb20c6bb0d1f556068eeb813db89892b645bec777 /com32/lib/syslinux
parentbcfd0df3c9778eff358926dffd35f870becff26b (diff)
downloadsyslinux-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.c91
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;
}