diff options
author | Erik Nolte <erik_nolte@acm.org> | 2011-10-06 14:31:37 -0600 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2011-10-14 10:57:46 +0100 |
commit | a98be5ba1deea4f0b46eb4273ea278e3e0eb87ea (patch) | |
tree | 17363a8abd6becd363e13e9663d09844e7122a90 | |
parent | 359718fa6c7ff177ef3413552f57a174d7205102 (diff) | |
download | febootstrap-a98be5ba1deea4f0b46eb4273ea278e3e0eb87ea.tar.gz febootstrap-a98be5ba1deea4f0b46eb4273ea278e3e0eb87ea.tar.xz febootstrap-a98be5ba1deea4f0b46eb4273ea278e3e0eb87ea.zip |
helper/init: Handle compressed modules transparently.
Detect libz and, if present, define HAS_LIBZ and add -lz to Makefile's
LIBS variable.
Add entry on optional zlib package requirement.
Detect both uncompressed and gzipped kernel modules.
Some Linux distros (like ArchLinux) use gzipped kernel modules with
filenames like ext2.ko.gz. This change modifies the filename pattern
from (e.g.) "ext2.ko" to "ext2.ko*".
When available, use libz to read the module.
The init_module system call requires uncompressed kernel module bytes.
On some systems (e.g. ArchLinux) the modules are gzipped on disk.
Libz is used to read and uncompress gzipped disk files (*.ko.gz) or
transparently read uncompressed modules (*.ko).
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | helper/ext2initrd.c | 30 | ||||
-rw-r--r-- | helper/init.c | 51 |
4 files changed, 66 insertions, 20 deletions
@@ -59,6 +59,8 @@ are building: qemu >= 0.13 kernel >= 2.6.36 + zlib - if your kernel uses gzipped modules + Building and installing ----------------------- diff --git a/configure.ac b/configure.ac index 23c876b..dca5032 100644 --- a/configure.ac +++ b/configure.ac @@ -86,6 +86,9 @@ AC_SUBST([APT_CACHE_DEPENDS_RECURSE_BROKEN]) dnl For ArchLinux handler. AC_CHECK_PROG(PACMAN,[pacman],[pacman],[no]) +dnl Support for gzipped kernel modules. +AC_CHECK_LIB([z],[gzopen]) + dnl Required programs, libraries. AC_PATH_PROG([MKE2FS],[mke2fs],[no], [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR]) diff --git a/helper/ext2initrd.c b/helper/ext2initrd.c index c4fc353..bb00c72 100644 --- a/helper/ext2initrd.c +++ b/helper/ext2initrd.c @@ -52,21 +52,21 @@ extern char _binary_init_start, _binary_init_end, _binary_init_size; * ext2 filesystem on it. */ static const char *kmods[] = { - "ext2.ko", - "ext4.ko", /* CONFIG_EXT4_USE_FOR_EXT23=y option might be set */ - "virtio*.ko", - "ide*.ko", - "libata*.ko", - "piix*.ko", - "scsi_transport_spi.ko", - "scsi_mod.ko", - "sd_mod.ko", - "sym53c8xx.ko", - "ata_piix.ko", - "sr_mod.ko", - "mbcache.ko", - "crc*.ko", - "libcrc*.ko", + "ext2.ko*", + "ext4.ko*", /* CONFIG_EXT4_USE_FOR_EXT23=y option might be set */ + "virtio*.ko*", + "ide*.ko*", + "libata*.ko*", + "piix*.ko*", + "scsi_transport_spi.ko*", + "scsi_mod.ko*", + "sd_mod.ko*", + "sym53c8xx.ko*", + "ata_piix.ko*", + "sr_mod.ko*", + "mbcache.ko*", + "crc*.ko*", + "libcrc*.ko*", NULL }; diff --git a/helper/init.c b/helper/init.c index 34a8450..447df8e 100644 --- a/helper/init.c +++ b/helper/init.c @@ -38,6 +38,10 @@ #include <asm/unistd.h> +#ifdef HAVE_LIBZ +#include <zlib.h> +#endif + extern long init_module (void *, unsigned long, const char *); /* translation taken from module-init-tools/insmod.c */ @@ -201,9 +205,40 @@ main () static void insmod (const char *filename) { + size_t size; + if (verbose) fprintf (stderr, "febootstrap: internal insmod %s\n", filename); +#ifdef HAVE_LIBZ + gzFile gzfp = gzopen (filename, "rb"); + int capacity = 64*1024; + char *buf = (char *) malloc (capacity); + int tmpsize = 8 * 1024; + char tmp[tmpsize]; + int num; + + size = 0; + + if (gzfp == NULL) { + fprintf (stderr, "insmod: gzopen failed: %s", filename); + exit (EXIT_FAILURE); + } + while ((num = gzread (gzfp, tmp, tmpsize)) > 0) { + if (num > capacity) { + buf = (char*) realloc (buf, size*2); + capacity = size; + } + memcpy (buf+size, tmp, num); + capacity -= num; + size += num; + } + if (num == -1) { + perror ("insmod: gzread"); + exit (EXIT_FAILURE); + } + gzclose (gzfp); +#else int fd = open (filename, O_RDONLY); if (fd == -1) { fprintf (stderr, "insmod: open: %s: %m\n", filename); @@ -214,24 +249,30 @@ insmod (const char *filename) perror ("insmod: fstat"); exit (EXIT_FAILURE); } - char buf[st.st_size]; - long offset = 0; + size = st.st_size; + char buf[size]; + size_t offset = 0; do { - long rc = read (fd, buf + offset, st.st_size - offset); + ssize_t rc = read (fd, buf + offset, size - offset); if (rc == -1) { perror ("insmod: read"); exit (EXIT_FAILURE); } offset += rc; - } while (offset < st.st_size); + } while (offset < size); close (fd); +#endif - if (init_module (buf, st.st_size, "") != 0) { + if (init_module (buf, size, "") != 0) { fprintf (stderr, "insmod: init_module: %s: %s\n", filename, moderror (errno)); /* However ignore the error because this can just happen because * of a missing device. */ } + +#ifdef HAVE_LIBZ + free (buf); +#endif } /* Mount /proc unless it's mounted already. */ |