Comboot/Com32 changes for unspecified file lengths
authorH. Peter Anvin <hpa@zytor.com>
Wed, 27 Feb 2008 20:40:31 +0000 (12:40 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 27 Feb 2008 20:40:31 +0000 (12:40 -0800)
Handle unspecified file length for comboot/com32 modules; do changes
to the appropriate part of libcom32 to handle this properly.

com32/include/syslinux/loadfile.h
com32/lib/sys/fileread.c
com32/lib/sys/vesa/background.c
com32/lib/syslinux/loadfile.c
comboot.inc
doc/comboot.doc

index fbda589..c565cc9 100644 (file)
@@ -2,11 +2,13 @@
 #define LIBUTIL_LOADFILE_H
 
 #include <stddef.h>
+#include <stdio.h>
 
 /* loadfile() returns the true size of the file, but will guarantee valid,
    zero-padded memory out to this boundary. */
 #define LOADFILE_ZERO_PAD      64
 
 int loadfile(const char *, void **, size_t *);
+int floadfile(FILE *, void **, size_t *, const void *, size_t);
 
 #endif
index fe20e64..5e528b1 100644 (file)
@@ -65,7 +65,7 @@ ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
       }
 
       fp->i.filedes = oreg.esi.w[0];
-      fp->i.nbytes = min(fp->i.length-fp->i.offset, (unsigned)MAXBLOCK);
+      fp->i.nbytes = oreg.ecx.l;
       fp->i.datap = fp->i.buf;
       memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
     }
index 3bdda20..f141a6a 100644 (file)
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <minmax.h>
+#include <syslinux/loadfile.h>
 #include "vesa.h"
 #include "video.h"
 
@@ -172,19 +173,16 @@ static int jpeg_sig_cmp(uint8_t *bytes, int len)
 static int read_jpeg_file(FILE *fp, uint8_t *header, int len)
 {
   struct jdec_private *jdec = NULL;
-  unsigned char *jpeg_file = NULL;
-  size_t length_of_file = filesize(fp);
+  void *jpeg_file = NULL;
+  size_t length_of_file;
   unsigned int width, height;
   int rv = -1;
   unsigned char *components[1];
   unsigned int bytes_per_row[1];
 
-  jpeg_file = malloc(length_of_file);
-  if (!jpeg_file)
-    goto err;
-
-  memcpy(jpeg_file, header, len);
-  if (fread(jpeg_file+len, 1, length_of_file-len, fp) != length_of_file-len)
+  rv = floadfile(fp, &jpeg_file, &length_of_file, header, len);
+  fclose(fp);
+  if (rv)
     goto err;
 
   jdec = tinyjpeg_init();
index ec7a603..f5479da 100644 (file)
 
 #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;
 }
index 7c0f40f..646f44d 100644 (file)
@@ -425,6 +425,7 @@ comapi_read:
                jnc .noteof
                xor si,si               ; SI <- 0 on EOF, CF <- 0
 .noteof:       mov P_SI,si
+               mov P_ECX,ecx
                ret
 
 ;
index c4e303a..41dfb9f 100644 (file)
@@ -315,7 +315,7 @@ AX=0007h [2.08] Read file
                ES:BX   buffer
                CX      number of blocks to read
        Output: SI      file handle, or 0 if EOF was reached
-               EAX     number of bytes read [3.70]
+               ECX     number of bytes read [3.70]
 
        Read blocks from a file.  Note that the file handle that is
        returned in SI may not be the same value that was passed in.
@@ -323,7 +323,7 @@ AX=0007h [2.08] Read file
        If end of file was reached (SI=0), the file was automatically
        closed.
 
-       In 3.70 or later, EAX returns the number of bytes read.  This
+       In 3.70 or later, ECX returns the number of bytes read.  This
        will always be a multiple of the block size unless EOF is
        reached.