summaryrefslogtreecommitdiffstats
path: root/helper
diff options
context:
space:
mode:
authorErik Nolte <erik_nolte@acm.org>2011-10-06 14:31:37 -0600
committerRichard W.M. Jones <rjones@redhat.com>2011-10-14 10:57:46 +0100
commita98be5ba1deea4f0b46eb4273ea278e3e0eb87ea (patch)
tree17363a8abd6becd363e13e9663d09844e7122a90 /helper
parent359718fa6c7ff177ef3413552f57a174d7205102 (diff)
downloadfebootstrap-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).
Diffstat (limited to 'helper')
-rw-r--r--helper/ext2initrd.c30
-rw-r--r--helper/init.c51
2 files changed, 61 insertions, 20 deletions
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. */