#define LOADFILE_ZERO_PAD 64
int loadfile(const char *, void **, size_t *);
+int zloadfile(const char *, void **, size_t *);
int floadfile(FILE *, void **, size_t *, const void *, size_t);
#endif
sys/entry.o sys/exit.o sys/argv.o sys/times.o \
sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \
sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \
- sys/isatty.o sys/fstat.o sys/openconsole.o sys/line_input.o \
+ sys/isatty.o sys/fstat.o \
+ \
+ sys/zfile.o sys/zfopen.o \
+ \
+ sys/openconsole.o sys/line_input.o \
sys/colortable.o sys/screensize.o \
\
sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o \
syslinux/run_default.o syslinux/run_command.o \
syslinux/cleanup.o syslinux/localboot.o syslinux/runimage.o \
\
- syslinux/loadfile.o \
+ syslinux/loadfile.o syslinux/floadfile.o syslinux/zloadfile.o \
+ \
syslinux/load_linux.o syslinux/initramfs.o \
syslinux/initramfs_file.o syslinux/initramfs_loadfile.o \
syslinux/initramfs_archive.o \
const struct input_dev *iop; /* Input operations */
const struct output_dev *oop; /* Output operations */
+ /* Output file data */
+ struct {
+ int rows, cols; /* Rows and columns */
+ } o;
+
/* Structure used for input blocking */
struct {
int blocklg2; /* Blocksize log 2 */
uint16_t _filler; /* Unused */
size_t nbytes; /* Number of bytes available in buffer */
char *datap; /* Current data pointer */
+ void *pvt; /* Private pointer for driver */
char buf[MAXBLOCK];
} i;
-
- /* Output file data */
- struct {
- int rows, cols; /* Rows and columns */
- } o;
};
extern struct file_info __file_info[NFILES];
#include <minmax.h>
#include "file.h"
-ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
+int __file_get_block(struct file_info *fp)
{
com32sys_t ireg, oreg;
- char *bufp = buf;
- size_t n = 0;
- size_t ncopy;
memset(&ireg, 0, sizeof ireg);
ireg.eax.w[0] = 0x0007; /* Read file */
ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
ireg.es = SEG(__com32.cs_bounce);
+ ireg.esi.w[0] = fp->i.filedes;
+ ireg.ecx.w[0] = MAXBLOCK >> fp->i.blocklg2;
+
+ __intcall(0x22, &ireg, &oreg);
+
+ if ( oreg.eflags.l & EFLAGS_CF ) {
+ errno = EIO;
+ return -1;
+ }
+
+ fp->i.filedes = oreg.esi.w[0];
+ fp->i.nbytes = oreg.ecx.l;
+ fp->i.datap = fp->i.buf;
+ memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
+
+ return 0;
+}
+
+ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
+{
+ char *bufp = buf;
+ ssize_t n = 0;
+ size_t ncopy;
while ( count ) {
if ( fp->i.nbytes == 0 ) {
if ( fp->i.offset >= fp->i.length || !fp->i.filedes )
return n; /* As good as it gets... */
- ireg.esi.w[0] = fp->i.filedes;
- ireg.ecx.w[0] = MAXBLOCK >> fp->i.blocklg2;
-
- __intcall(0x22, &ireg, &oreg);
-
- if ( oreg.eflags.l & EFLAGS_CF ) {
- errno = EIO;
- return -1;
- }
-
- fp->i.filedes = oreg.esi.w[0];
- fp->i.nbytes = oreg.ecx.l;
- fp->i.datap = fp->i.buf;
- memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
+ if ( __file_get_block(fp) )
+ return n ? n : -1;
}
ncopy = min(count, fp->i.nbytes);
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <syslinux/zio.h>
+
+#include "file.h"
+#include "zlib.h"
+
+/*
+ * zopen.c
+ *
+ * Open an ordinary file, possibly compressed; if so, insert
+ * an appropriate decompressor.
+ */
+
+int __file_get_block(struct file_info *fp);
+int __file_close(struct file_info *fp);
+
+static ssize_t gzip_file_read(struct file_info *, void *, size_t);
+static int gzip_file_close(struct file_info *);
+
+static const struct input_dev gzip_file_dev = {
+ .dev_magic = __DEV_MAGIC,
+ .flags = __DEV_FILE | __DEV_INPUT,
+ .fileflags = O_RDONLY,
+ .read = gzip_file_read,
+ .close = gzip_file_close,
+ .open = NULL,
+};
+
+static int gzip_file_init(struct file_info *fp)
+{
+ z_streamp zs = calloc(1, sizeof(z_stream));
+
+ if (!zs)
+ return -1;
+
+ fp->i.pvt = zs;
+
+ zs->next_in = (void *)fp->i.datap;
+ zs->avail_in = fp->i.nbytes;
+
+ if (inflateInit2(zs, 15+32) != Z_OK) {
+ errno = EIO;
+ return -1;
+ }
+
+ fp->iop = &gzip_file_dev;
+ fp->i.length = -1; /* Unknown */
+
+ return 0;
+}
+
+static ssize_t gzip_file_read(struct file_info *fp, void *ptr, size_t n)
+{
+ z_streamp zs = fp->i.pvt;
+ int rv;
+ ssize_t bytes;
+ ssize_t nout = 0;
+ unsigned char *p = ptr;
+
+ while ( n ) {
+ zs->next_out = p;
+ zs->avail_out = n;
+
+ if (!zs->avail_in && fp->i.filedes) {
+ if (__file_get_block(fp))
+ return nout ? nout : -1;
+
+ zs->next_in = (void *)fp->i.datap;
+ zs->avail_in = fp->i.nbytes;
+ }
+
+ rv = inflate(zs, Z_SYNC_FLUSH);
+
+ bytes = n - zs->avail_out;
+ nout += bytes;
+ p += bytes;
+ n -= bytes;
+
+ switch (rv) {
+ case Z_DATA_ERROR:
+ case Z_NEED_DICT:
+ case Z_BUF_ERROR:
+ case Z_STREAM_ERROR:
+ default:
+ errno = EIO;
+ return nout ? nout : -1;
+ case Z_MEM_ERROR:
+ errno = ENOMEM;
+ return nout ? nout : -1;
+ case Z_STREAM_END:
+ return nout;
+ case Z_OK:
+ break;
+ }
+ }
+
+ return nout;
+}
+
+static int gzip_file_close(struct file_info *fp)
+{
+ z_streamp zs = fp->i.pvt;
+
+ inflateEnd(zs);
+ free(zs);
+ return __file_close(fp);
+}
+
+int zopen(const char *pathname, int flags, ...)
+{
+ int fd, rv;
+ struct file_info *fp;
+
+ /* We don't actually give a hoot about the creation bits... */
+ fd = open(pathname, flags, 0);
+
+ if ( fd < 0 )
+ return -1;
+
+ fp = &__file_info[fd];
+
+ /* Need to get the first block into the buffer, but not consumed */
+ if ( __file_get_block(fp) )
+ goto err;
+
+ if (fp->i.nbytes >= 14 &&
+ (uint8_t)fp->i.buf[0] == 037 &&
+ (uint8_t)fp->i.buf[1] == 0213 && /* gzip */
+ fp->i.buf[2] == 8) /* deflate */
+ rv = gzip_file_init(fp);
+ else
+ rv = 0; /* Plain file */
+
+ if (!rv)
+ return fd;
+
+ err:
+ close(fd);
+ return -1;
+}
--- /dev/null
+/*
+ * zfopen.c
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslinux/zio.h>
+
+FILE *zfopen(const char *file, const char *mode)
+{
+ int flags = O_RDONLY;
+ int plus = 0;
+ int fd;
+
+ while ( *mode ) {
+ switch ( *mode ) {
+ case 'r':
+ flags = O_RDONLY;
+ break;
+ case 'w':
+ flags = O_WRONLY|O_CREAT|O_TRUNC;
+ break;
+ case 'a':
+ flags = O_WRONLY|O_CREAT|O_APPEND;
+ break;
+ case '+':
+ plus = 1;
+ break;
+ }
+ mode++;
+ }
+
+ if ( plus ) {
+ flags = (flags & ~(O_RDONLY|O_WRONLY)) | O_RDWR;
+ }
+
+ fd = zopen(file, flags, 0666);
+
+ if ( fd < 0 )
+ return NULL;
+ else
+ return fdopen(fd, mode);
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * floadfile.c
+ *
+ * Read the contents of a data file into a malloc'd buffer
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <syslinux/loadfile.h>
+
+#define INCREMENTAL_CHUNK 1024*1024
+
+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;
+
+ clen = alen = 0;
+ data = NULL;
+
+ if ( fstat(fileno(f), &st) )
+ goto err;
+
+ 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;
+
+ 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:
+ if (data)
+ free(data);
+ return -1;
+}
*
* Copyright 2005-2008 H. Peter Anvin - All Rights Reserved
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
- * Boston MA 02111-1307, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
*
* ----------------------------------------------------------------------- */
return rv;
}
-
-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;
-
- clen = alen = 0;
- data = NULL;
-
- if ( fstat(fileno(f), &st) )
- goto err;
-
- 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;
-
- 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:
- if (data)
- free(data);
- return -1;
-}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * zloadfile.c
+ *
+ * Read the contents of a possibly compressed data file into a malloc'd buffer
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <syslinux/zio.h>
+
+#include <syslinux/loadfile.h>
+
+#define INCREMENTAL_CHUNK 1024*1024
+
+int zloadfile(const char *filename, void **ptr, size_t *len)
+{
+ FILE *f;
+ int rv;
+
+ f = zfopen(filename, "r");
+ if ( !f )
+ return -1;
+
+ rv = floadfile(f, ptr, len, NULL, 0);
+ fclose(f);
+
+ return rv;
+}