diff options
author | Richard Jones <rjones@trick.home.annexia.org> | 2009-07-28 17:55:35 +0100 |
---|---|---|
committer | Richard Jones <rjones@trick.home.annexia.org> | 2009-07-29 10:16:06 +0100 |
commit | 1f65b900f0f17a700035dea9a76b910504f4507c (patch) | |
tree | 7c204de9a25bdeb1e72653f466dbbeedc4948d1a /perl/lib | |
parent | 7cbd1bbdd5e613561ea7227081f7ddd666b98ee0 (diff) | |
download | libguestfs-1f65b900f0f17a700035dea9a76b910504f4507c.tar.gz libguestfs-1f65b900f0f17a700035dea9a76b910504f4507c.tar.xz libguestfs-1f65b900f0f17a700035dea9a76b910504f4507c.zip |
Lib.pm: Add file_architecture command.
This command detects the architecture of some types of binaries,
libraries, kernel modules and initrd images.
Diffstat (limited to 'perl/lib')
-rw-r--r-- | perl/lib/Sys/Guestfs/Lib.pm | 161 |
1 files changed, 159 insertions, 2 deletions
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm index bc8be9db..081b4b9b 100644 --- a/perl/lib/Sys/Guestfs/Lib.pm +++ b/perl/lib/Sys/Guestfs/Lib.pm @@ -300,6 +300,163 @@ sub resolve_windows_path return $path; } +=head2 file_architecture + + $arch = file_architecture ($g, $path) + +The C<file_architecture> function lets you get the architecture for a +particular binary or library in the guest. By "architecture" we mean +what processor it is compiled for (eg. C<i586> or C<x86_64>). + +The function works on at least the following types of files: + +=over 4 + +=item * + +many types of Un*x binary + +=item * + +many types of Un*x shared library + +=item * + +Windows Win32 and Win64 binaries + +=item * + +Windows Win32 and Win64 DLLs + +Win32 binaries and DLLs return C<i386>. + +Win64 binaries and DLLs return C<x86_64>. + +=item * + +Linux kernel modules + +=item * + +Linux new-style initrd images + +=item * + +some non-x86 Linux vmlinuz kernels + +=back + +What it can't do currently: + +=over 4 + +=item * + +static libraries (libfoo.a) + +=item * + +Linux old-style initrd as compressed ext2 filesystem (RHEL 3) + +=item * + +x86 Linux vmlinuz kernels + +x86 vmlinuz images (bzImage format) consist of a mix of 16-, 32- and +compressed code, and are horribly hard to unpack. If you want to find +the architecture of a kernel, use the architecture of the associated +initrd or kernel module(s) instead. + +=back + +=cut + +sub _elf_arch_to_canonical +{ + local $_ = shift; + + if ($_ eq "Intel 80386") { + return "i386"; + } elsif ($_ eq "Intel 80486") { + return "i486"; # probably not in the wild + } elsif ($_ eq "x86-64") { + return "x86_64"; + } elsif (/SPARC32/) { + return "sparc"; + } elsif (/SPARC V9/) { + return "sparc64"; + } elsif ($_ eq "IA-64") { + return "ia64"; + } elsif (/64.*PowerPC/) { + return "ppc64"; + } elsif (/PowerPC/) { + return "ppc"; + } else { + warn __x("returning non-canonical architecture type '{arch}'", + arch => $_); + return $_; + } +} + +my @_initrd_binaries = ("nash", "modprobe", "sh", "bash"); + +sub file_architecture +{ + local $_; + my $g = shift; + my $path = shift; + + # Our basic tool is 'file' ... + my $file = $g->file ($path); + + if ($file =~ /ELF.*(?:executable|shared object|relocatable), (.+?),/) { + # ELF executable or shared object. We need to convert + # what file(1) prints into the canonical form. + return _elf_arch_to_canonical ($1); + } elsif ($file =~ /PE32 executable/) { + return "i386"; # Win32 executable or DLL + } elsif ($file =~ /PE32\+ executable/) { + return "x86_64"; # Win64 executable or DLL + } + + elsif ($file =~ /cpio archive/) { + # Probably an initrd. + my $zcat = "cat"; + if ($file =~ /gzip/) { + $zcat = "zcat"; + } elsif ($file =~ /bzip2/) { + $zcat = "bzcat"; + } + + # Download and unpack it to find a binary file. + my $dir = tempdir (CLEANUP => 1); + $g->download ($path, "$dir/initrd"); + + my $bins = join " ", map { "bin/$_" } @_initrd_binaries; + my $cmd = "cd $dir && $zcat initrd | cpio -id $bins"; + my $r = system ($cmd); + die __x("cpio command failed: {error}", error => $?) + unless $r == 0; + + foreach my $bin (@_initrd_binaries) { + if (-f "$dir/bin/$bin") { + open PIPE, "file $dir/bin/$bin |"; + local $/ = undef; + $_ = <PIPE>; + if (/ELF.*executable, (.+?),/) { + return _elf_arch_to_canonical ($1); + } + } + } + + die __x("file_architecture: no known binaries found in initrd image: {path}", + path => $path); + } + + die __x("file_architecture: unknown architecture: {path}", + path => $path); +} + =head1 OPERATING SYSTEM INSPECTION FUNCTIONS The functions in this section can be used to inspect the operating @@ -1094,8 +1251,8 @@ sub mount_operating_system $g->umount_all (); The C<inspect_in_detail> function inspects the mounted operating -system for installed applications, installed kernels, kernel modules -and more. +system for installed applications, installed kernels, kernel modules, +system architecture, and more. It adds extra keys to the existing C<%os> hash reflecting what it finds. These extra keys are: |