When building the mini initrd, previously we copied the modules into
the initrd as-is, so for example if the module was xz-compressed, we
copied the foo.ko.xz file to the initrd. This requires that the mini
init binary is linked to zlib & lzma, so that it knows how to
uncompress these modules when insmoding them at boot time. Also since
the init is statically linked, it required _static_ versions of these
libraries.
This changes things so that the modules are uncompressed in the mini
initrd, so they are a little bit larger, but the init binary no longer
needs to be statically linked to zlib & lzma.
The init binary is smaller (966K -> 837K), but because we are storing
uncompressed modules in the mini initrd, the initrd as a whole becomes
larger (1.4M -> 2.6M)
However there are benefits to this change:
- The code in the init binary is much simpler.
- Removes the dependency on static zlib & lzma.
- We can use an alternate libc to make a much smaller init binary
(see following commits).
---
README | 4 +-
configure.ac | 74 ++-------------------------
src/Makefile.am | 1 -
src/config.ml.in | 2 +
src/ext2_initrd.ml | 28 ++++++++++-
src/init.c | 145 -----------------------------------------------------
6 files changed, 34 insertions(+), 220 deletions(-)
diff --git a/README b/README
index 34949a2..56a28f6 100644
--- a/README
+++ b/README
@@ -97,9 +97,9 @@ are building:
qemu >= 0.13
kernel >= 2.6.36
- zlib (statically linked) - if your kernel uses gzipped modules
+ gunzip (command) - if your kernel uses gzipped modules
- xz (statically linked) - if your kernel uses xz-compressed modules
+ unxz (command) - if your kernel uses xz-compressed modules
Building and installing
-----------------------
diff --git a/configure.ac b/configure.ac
index 126366b..0fe88c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,77 +127,11 @@ dnl Check for fakeroot, only used a few drivers where the host
package
dnl manager contains broken/unnecessary tests for root privs.
AC_PATH_PROG(FAKEROOT,[fakeroot],[no])
-dnl Support for compressed input files, gzipped kernel modules.
-AC_CHECK_HEADER([zlib.h],[
- AC_CHECK_LIB([z],[gzopen],[
- zlib=yes
- ZLIB_LIBS=-lz
+dnl Check for gunzip, only needed if you have gzip-compressed kernel modules.
+AC_PATH_PROG(GUNZIP,[gunzip],[no])
- AC_MSG_CHECKING([for gzip static library])
- old_CFLAGS="$CFLAGS"
- old_LDFLAGS="$LDFLAGS"
- old_LIBS="$LIBS"
- CFLAGS="$CFLAGS -static"
- LDFLAGS="$LDFLAGS -static"
- LIBS="$LIBS -lz"
- AC_LINK_IFELSE([
- #include <stdio.h>
- #include <stdlib.h>
- #include <zlib.h>
- int main () { gzFile g = gzopen ("test", "rb"); exit (g ?
1 : 0); }
- ],[
- zlib_static=yes
- ZLIB_STATIC_LIBS="$ZLIB_LIBS"
- AC_MSG_RESULT([yes])
- ],[
- AC_MSG_RESULT([no])
- ])
- CFLAGS="$old_CFLAGS"
- LDFLAGS="$old_LDFLAGS"
- LIBS="$old_LIBS"
- ])
-])
-if test "x$zlib" = "xyes"; then
- AC_DEFINE([HAVE_ZLIB],[1],[Define if you have zlib])
- AC_SUBST([ZLIB_LIBS])
-fi
-if test "x$zlib_static" = "xyes"; then
- AC_DEFINE([HAVE_ZLIB_STATIC],[1],[Define if you have static zlib])
- AC_SUBST([ZLIB_STATIC_LIBS])
-fi
-
-dnl Support for xzed kernel modules.
-AC_CHECK_HEADER([lzma.h],[
- AC_CHECK_LIB([lzma],[lzma_code],[
- AC_MSG_CHECKING([for xz static library])
- old_CFLAGS="$CFLAGS"
- old_LDFLAGS="$LDFLAGS"
- old_LIBS="$LIBS"
- CFLAGS="$CFLAGS -static"
- LDFLAGS="$LDFLAGS -static"
- LIBS="$LIBS -llzma"
- AC_LINK_IFELSE([
- #include <stdio.h>
- #include <stdlib.h>
- #include <lzma.h>
- int main () { lzma_stream s = LZMA_STREAM_INIT;
- exit (s.next_in == NULL ? 1 : 0); }
- ],[
- lzma_static=yes
- LZMA_STATIC_LIBS="-llzma"
- AC_MSG_RESULT([yes])
- ],[
- AC_MSG_RESULT([no])
- ])
- CFLAGS="$old_CFLAGS"
- LDFLAGS="$old_LDFLAGS"
- LIBS="$old_LIBS"
- ])
-])
-if test "x$lzma_static" = "xyes"; then
- AC_DEFINE([HAVE_LZMA_STATIC],[1],[Define if you have static lzma])
- AC_SUBST([LZMA_STATIC_LIBS])
-fi
+dnl Check for unxz, only needed if you have xz-compressed kernel modules.
+AC_PATH_PROG(UNXZ,[unxz],[no])
dnl mke2fs.
AC_PATH_PROG([MKE2FS],[mke2fs],[no],
diff --git a/src/Makefile.am b/src/Makefile.am
index 6261c86..5a601fe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -143,7 +143,6 @@ noinst_PROGRAMS = init
init_SOURCES = init.c
init_CFLAGS = -static
init_LDFLAGS = -static
-init_LDADD = $(ZLIB_STATIC_LIBS) $(LZMA_STATIC_LIBS)
CLEANFILES += ext2init-bin.S
diff --git a/src/config.ml.in b/src/config.ml.in
index 42cf833..19545b6 100644
--- a/src/config.ml.in
+++ b/src/config.ml.in
@@ -29,12 +29,14 @@ let dpkg_deb = "@DPKG_DEB@"
let dpkg_query = "@DPKG_QUERY@"
let dpkg_divert = "@DPKG_DIVERT@"
let fakeroot = "@FAKEROOT@"
+let gunzip = "@GUNZIP@"
let makepkg = "@MAKEPKG@"
let pacman = "@PACMAN@"
let pactree = "@PACTREE@"
let pacman_g2 = "@PACMAN_G2@"
let rpm = "@RPM@"
let rpm2cpio = "@RPM2CPIO@"
+let unxz = "@UNXZ@"
let urpmi = "@URPMI@"
let yumdownloader = "@YUMDOWNLOADER@"
let zypper = "@ZYPPER@"
diff --git a/src/ext2_initrd.ml b/src/ext2_initrd.ml
index b34f0e6..e49a19d 100644
--- a/src/ext2_initrd.ml
+++ b/src/ext2_initrd.ml
@@ -1,5 +1,5 @@
(* supermin 5
- * Copyright (C) 2009-2014 Red Hat Inc.
+ * Copyright (C) 2009-2016 Red Hat Inc.
*
* 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
@@ -105,8 +105,32 @@ let rec build_initrd debug tmpdir modpath initrd =
sprintf "cp -t %s %s" (quote initdir) (quote (modpath // modl)) in
run_command cmd;
+ (* Uncompress the module, if the name ends in .xz or .gz. *)
+ let basename = Filename.basename modl in
+ let basename =
+ let len = String.length basename in
+ if Config.unxz <> "no" && Filename.check_suffix
basename ".xz"
+ then (
+ let cmd = sprintf "%s %s"
+ (quote Config.unxz)
+ (quote (initdir // basename)) in
+ run_command cmd;
+ String.sub basename 0 (len-3)
+ )
+ else if Config.gunzip <> "no" &&
+ Filename.check_suffix basename ".gz"
+ then (
+ let cmd = sprintf "%s %s"
+ (quote Config.gunzip)
+ (quote (initdir // basename)) in
+ run_command cmd;
+ String.sub basename 0 (len-3)
+ )
+ else
+ basename in
+
(* Write module name to 'modules' file. *)
- fprintf chan "%s\n" (Filename.basename modl);
+ fprintf chan "%s\n" basename;
incr loaded
)
) set
diff --git a/src/init.c b/src/init.c
index 814243a..25d6bc6 100644
--- a/src/init.c
+++ b/src/init.c
@@ -42,14 +42,6 @@
#include <asm/unistd.h>
-#ifdef HAVE_ZLIB_STATIC
-#include <zlib.h>
-#endif
-
-#ifdef HAVE_LZMA_STATIC
-#include <lzma.h>
-#endif
-
/* Maximum time to wait for the root device to appear (seconds).
*
* On slow machines with lots of disks (Koji running the 255 disk test
@@ -102,12 +94,6 @@ main ()
print_uptime ();
fprintf (stderr, "supermin: ext2 mini initrd starting up: "
PACKAGE_VERSION
-#ifdef HAVE_ZLIB_STATIC
- " zlib"
-#endif
-#ifdef HAVE_LZMA_STATIC
- " xz"
-#endif
"\n");
read_cmdline ();
@@ -283,20 +269,6 @@ main ()
exit (EXIT_FAILURE);
}
-#if HAVE_LZMA_STATIC
-static int
-ends_with (const char *str, const char *suffix)
-{
- if (!str || !suffix)
- return 0;
- size_t lenstr = strlen (str);
- size_t lensuffix = strlen (suffix);
- if (lensuffix > lenstr)
- return 0;
- return strncmp (str + lenstr - lensuffix, suffix, lensuffix) == 0;
-}
-#endif
-
static void
insmod (const char *filename)
{
@@ -305,118 +277,6 @@ insmod (const char *filename)
if (verbose)
fprintf (stderr, "supermin: internal insmod %s\n", filename);
-#ifdef HAVE_ZLIB_STATIC
- int capacity = 64*1024;
- char *buf = (char *) malloc (capacity);
- int tmpsize = 8 * 1024;
- char tmp[tmpsize];
- int num;
-
- errno = 0;
- size = 0;
-
- if (!buf) {
- perror("malloc");
- exit (EXIT_FAILURE);
- }
-
-#ifdef HAVE_LZMA_STATIC
- if (ends_with(filename, ".xz")) {
- lzma_stream strm = LZMA_STREAM_INIT;
- lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX,
- LZMA_CONCATENATED);
- if (verbose)
- fprintf (stderr, "supermin: running xz\n");
- FILE *fd = fopen (filename, "r");
- if (!fd) {
- perror("popen failed");
- exit (EXIT_FAILURE);
- }
- char tmp_out[tmpsize];
- strm.avail_in = 0;
- strm.next_out = tmp_out;
- strm.avail_out = tmpsize;
-
- lzma_action action = LZMA_RUN;
-
- while (1) {
- if (strm.avail_in == 0) {
- strm.next_in = tmp;
- strm.avail_in = fread(tmp, 1, tmpsize, fd);
-
- if (ferror(fd)) {
- // POSIX says that fread() sets errno if
- // an error occurred. ferror() doesn't
- // touch errno.
- perror("Error reading input file");
- exit (EXIT_FAILURE);
- }
- if (feof(fd)) action = LZMA_FINISH;
- }
-
- ret = lzma_code(&strm, action);
-
- // Write and check write error before checking decoder error.
- // This way as much data as possible gets written to output
- // even if decoder detected an error.
- if (strm.avail_out == 0 || ret != LZMA_OK) {
- const size_t num = tmpsize - strm.avail_out;
- if (num > capacity) {
- buf = (char*) realloc (buf, size*2);
- if (!buf) {
- perror("realloc");
- exit (EXIT_FAILURE);
- }
- capacity = size;
- }
- memcpy (buf+size, tmp_out, num);
- capacity -= num;
- size += num;
- strm.next_out = tmp_out;
- strm.avail_out = tmpsize;
- }
- if (ret != LZMA_OK) {
- if (ret == LZMA_STREAM_END) {
- break;
- } else {
- perror("internal error");
- exit(EXIT_FAILURE);
- }
- }
- }
- fclose (fd);
- if (verbose)
- fprintf (stderr, "done with xz %d read\n", size);
- } else {
-#endif
- gzFile gzfp = gzopen (filename, "rb");
- 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);
- if (!buf) {
- perror("realloc");
- exit (EXIT_FAILURE);
- }
- capacity = size;
- }
- memcpy (buf+size, tmp, num);
- capacity -= num;
- size += num;
- }
- if (num == -1) {
- perror ("insmod: gzread");
- exit (EXIT_FAILURE);
- }
- gzclose (gzfp);
-#ifdef HAVE_LZMA_STATIC
-}
-#endif
-
-#else
int fd = open (filename, O_RDONLY);
if (fd == -1) {
fprintf (stderr, "insmod: open: %s: %m\n", filename);
@@ -439,7 +299,6 @@ insmod (const char *filename)
offset += rc;
} while (offset < size);
close (fd);
-#endif
if (init_module (buf, size, "") != 0) {
fprintf (stderr, "insmod: init_module: %s: %s\n", filename, moderror
(errno));
@@ -447,10 +306,6 @@ insmod (const char *filename)
* of a missing device.
*/
}
-
-#ifdef HAVE_ZLIB_STATIC
- free (buf);
-#endif
}
/* Mount /proc unless it's mounted already. */
--
2.5.0