From 4dff42aa13dd726fb6b02843d0f4db4b4b330fe3 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 29 Jun 2009 15:16:40 +0100 Subject: [PATCH] Add 'initrd-list' command to list contents of initrd images. Add 'initrd-list' command to list the files inside (new-style) initrd images. Update virt-inspector to use this instead of the less efficient download/unpack locally method. --- .gitignore | 1 + daemon/Makefile.am | 1 + daemon/initrd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++ images/Makefile.am | 8 ++++- inspector/virt-inspector.pl | 45 ++++++----------------- src/generator.ml | 16 +++++++++ 6 files changed, 124 insertions(+), 35 deletions(-) create mode 100644 daemon/initrd.c diff --git a/.gitignore b/.gitignore index bbb1045..4d1da44 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ images/100kallnewlines images/100kallspaces images/100krandom images/10klines +images/initrd images/test.sqsh initramfs initramfs.timestamp diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 2884e93..88c382c 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -43,6 +43,7 @@ guestfsd_SOURCES = \ guestfsd.c \ headtail.c \ hexdump.c \ + initrd.c \ ls.c \ lvm.c \ mount.c \ diff --git a/daemon/initrd.c b/daemon/initrd.c new file mode 100644 index 0000000..513ed8d --- /dev/null +++ b/daemon/initrd.c @@ -0,0 +1,88 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include + +#include "../src/guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" + +char ** +do_initrd_list (char *path) +{ + FILE *fp; + int len; + char *cmd; + char filename[PATH_MAX]; + char **filenames = NULL; + int size = 0, alloc = 0; + + NEED_ROOT (NULL); + ABS_PATH (path, NULL); + + /* "zcat /sysroot/ | cpio --quiet -it", but path must be quoted. */ + len = 64 + 2 * strlen (path); + cmd = malloc (len); + if (!cmd) { + reply_with_perror ("malloc"); + return NULL; + } + + strcpy (cmd, "zcat /sysroot"); + shell_quote (cmd+13, len-13, path); + strcat (cmd, " | cpio --quiet -it"); + + fprintf (stderr, "%s\n", cmd); + + fp = popen (cmd, "r"); + if (fp == NULL) { + reply_with_perror ("popen: %s", cmd); + free (cmd); + return NULL; + } + free (cmd); + + while (fgets (filename, sizeof filename, fp) != NULL) { + len = strlen (filename); + if (len > 0 && filename[len-1] == '\n') + filename[len-1] = '\0'; + + if (add_string (&filenames, &size, &alloc, filename) == -1) { + pclose (fp); + return NULL; + } + } + + if (add_string (&filenames, &size, &alloc, NULL) == -1) { + pclose (fp); + return NULL; + } + + if (pclose (fp) == -1) { + reply_with_perror ("pclose"); + free_strings (filenames); + return NULL; + } + + return filenames; +} diff --git a/images/Makefile.am b/images/Makefile.am index 71d63a8..f2dd31b 100644 --- a/images/Makefile.am +++ b/images/Makefile.am @@ -26,7 +26,8 @@ noinst_DATA = test.sqsh CLEANFILES = test.sqsh squash_files = helloworld.tar helloworld.tar.gz empty known-1 known-2 known-3 \ - 100kallzeroes 100kallnewlines 100kallspaces 100krandom 10klines + 100kallzeroes 100kallnewlines 100kallspaces 100krandom 10klines \ + initrd test.sqsh: $(squash_files) rm -f $@ @@ -60,3 +61,8 @@ test.sqsh: $(squash_files) i=$$(($$i+1)); \ done > $@-t mv $@-t $@ + +initrd: empty known-1 known-2 known-3 + rm -f $@ $@-t + for f in $^; do echo $$f; done | cpio -o -H newc | gzip --best > $@-t + mv $@-t $@ diff --git a/inspector/virt-inspector.pl b/inspector/virt-inspector.pl index bd8de70..f12af42 100755 --- a/inspector/virt-inspector.pl +++ b/inspector/virt-inspector.pl @@ -727,9 +727,6 @@ sub find_filesystem # we don't need to know. if ($output !~ /.*fish$/) { - # Temporary directory for use by check_for_initrd. - my $dir = tempdir (CLEANUP => 1); - my $root_dev; foreach $root_dev (sort keys %oses) { my $mounts = $oses{$root_dev}->{mounts}; @@ -744,7 +741,7 @@ if ($output !~ /.*fish$/) { check_for_kernels ($root_dev); if ($oses{$root_dev}->{os} eq "linux") { check_for_modprobe_aliases ($root_dev); - check_for_initrd ($root_dev, $dir); + check_for_initrd ($root_dev); } $g->umount_all (); @@ -898,42 +895,22 @@ sub check_for_initrd { local $_; my $root_dev = shift; - my $dir = shift; my %initrd_modules; foreach my $initrd ($g->ls ("/boot")) { if ($initrd =~ m/^initrd-(.*)\.img$/ && $g->is_file ("/boot/$initrd")) { my $version = $1; - my @modules = (); - # We have to download these to a temporary file. - $g->download ("/boot/$initrd", "$dir/initrd"); - - my $cmd = "zcat $dir/initrd | file -"; - open P, "$cmd |" or die "$cmd: $!"; - my $lines; - { local $/ = undef; $lines =

; } - close P; - if ($lines =~ /ext\d filesystem data/) { - # Before initramfs came along, these were compressed - # ext2 filesystems. We could run another libguestfs - # instance to unpack these, but punt on them for now. (XXX) - warn "initrd image is unsupported ext2/3/4 filesystem\n"; - } - elsif ($lines =~ /cpio/) { - my $cmd = "zcat $dir/initrd | cpio --quiet -it"; - open P, "$cmd |" or die "$cmd: $!"; - while (

) { - push @modules, $1 - if m,([^/]+)\.ko$, || m,([^/]+)\.o$,; - } - close P; - unlink "$dir/initrd"; - $initrd_modules{$version} = \@modules; - } - else { - # What? - warn "unrecognized initrd image: $lines\n"; + my @modules; + + eval { + @modules = $g->initrd_list ("/boot/$initrd"); + }; + unless ($@) { + @modules = grep { m,([^/]+)\.ko$, || m,([^/]+)\.o$, } @modules; + $initrd_modules{$version} = \@modules + } else { + warn "/boot/$initrd: could not read initrd format" } } } diff --git a/src/generator.ml b/src/generator.ml index 5885ff3..2dfc8cb 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -2599,6 +2599,22 @@ subdirectories (recursively). The result is the estimated size in I (ie. units of 1024 bytes)."); + ("initrd_list", (RStringList "filenames", [String "path"]), 128, [], + [InitBasicFS, Always, TestOutputList ( + [["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]; + ["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3"])], + "list files in an initrd", + "\ +This command lists out files contained in an initrd. + +The files are listed without any initial C character. The +files are listed in the order they appear (not necessarily +alphabetical). Directory names are listed as separate items. + +Old Linux kernels (2.4 and earlier) used a compressed ext2 +filesystem as initrd. We I support the newer initramfs +format (compressed cpio files)."); + ] let all_functions = non_daemon_functions @ daemon_functions -- 1.8.3.1