On RHEL 5, 'file' command prints 'AMD x86-64' for 'x86-64' arch.
[libguestfs.git] / perl / lib / Sys / Guestfs / Lib.pm
index 081b4b9..be17a30 100644 (file)
@@ -381,6 +381,8 @@ sub _elf_arch_to_canonical
        return "i486";  # probably not in the wild
     } elsif ($_ eq "x86-64") {
        return "x86_64";
+    } elsif ($_ eq "AMD x86-64") {
+       return "x86_64";
     } elsif (/SPARC32/) {
        return "sparc";
     } elsif (/SPARC V9/) {
@@ -433,16 +435,14 @@ sub file_architecture
        $g->download ($path, "$dir/initrd");
 
        my $bins = join " ", map { "bin/$_" } @_initrd_binaries;
-       my $cmd = "cd $dir && $zcat initrd | cpio -id $bins";
+       my $cmd = "cd $dir && $zcat initrd | cpio --quiet -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>;
+               $_ = `file $dir/bin/$bin`;
                if (/ELF.*executable, (.+?),/) {
                    return _elf_arch_to_canonical ($1);
                }
@@ -876,6 +876,17 @@ sub _check_linux_root
        }
        $r->{fstab} = \@fstab if @fstab;
     }
+
+    # Determine the architecture of this root.
+    my $arch;
+    foreach ("/bin/bash", "/bin/ls", "/bin/echo", "/bin/rm", "/bin/sh") {
+       if ($g->is_file ($_)) {
+           $arch = file_architecture ($g, $_);
+           last;
+       }
+    }
+
+    $r->{arch} = $arch if defined $arch;
 }
 
 # We only support NT.  The control file /boot.ini contains a list of
@@ -914,13 +925,30 @@ sub _check_windows_root
 
        if (defined $systemroot) {
            $r->{systemroot} = resolve_windows_path ($g, "/$systemroot");
-           if (defined $r->{systemroot} && $use_windows_registry) {
-               _check_windows_registry ($g, $r, $r->{systemroot});
+           if (defined $r->{systemroot}) {
+               _check_windows_arch ($g, $r, $r->{systemroot});
+               if ($use_windows_registry) {
+                   _check_windows_registry ($g, $r, $r->{systemroot});
+               }
            }
        }
     }
 }
 
+# Find Windows userspace arch.
+
+sub _check_windows_arch
+{
+    local $_;
+    my $g = shift;
+    my $r = shift;
+    my $systemroot = shift;
+
+    my $cmd_exe =
+       resolve_windows_path ($g, $r->{systemroot} . "/system32/cmd.exe");
+    $r->{arch} = file_architecture ($g, $cmd_exe) if $cmd_exe;
+}
+
 sub _check_windows_registry
 {
     local $_;
@@ -1034,6 +1062,10 @@ The C<\%os> hash contains the following keys (any can be omitted):
 
 Operating system type, eg. "linux", "windows".
 
+=item arch
+
+Operating system userspace architecture, eg. "i386", "x86_64".
+
 =item distro
 
 Operating system distribution, eg. "debian".
@@ -1118,6 +1150,7 @@ sub _get_os_version
         if exists $r->{root}->{package_format};
     $r->{package_management} = $r->{root}->{package_management}
         if exists $r->{root}->{package_management};
+    $r->{arch} = $r->{root}->{arch} if exists $r->{root}->{arch};
 }
 
 sub _assign_mount_points
@@ -1267,6 +1300,24 @@ List of applications.
 
 List of kernels.
 
+This is a hash of kernel version =E<gt> a hash with the following keys:
+
+=over 4
+
+=item version
+
+Kernel version.
+
+=item arch
+
+Kernel architecture (eg. C<x86-64>).
+
+=item modules
+
+List of modules.
+
+=back
+
 =item modprobe_aliases
 
 (For Linux VMs).
@@ -1359,14 +1410,21 @@ sub _check_for_kernels
 
                # List modules.
                my @modules;
-               foreach ($g->find ("/lib/modules/$_")) {
+               my $any_module;
+               my $prefix = "/lib/modules/$_";
+               foreach ($g->find ($prefix)) {
                    if (m,/([^/]+)\.ko$, || m,([^/]+)\.o$,) {
+                       $any_module = "$prefix$_" unless defined $any_module;
                        push @modules, $1;
                    }
                }
 
                $kernel{modules} = \@modules;
 
+               # Determine kernel architecture by looking at the arch
+               # of any kernel module.
+               $kernel{arch} = file_architecture ($g, $any_module);
+
                push @kernels, \%kernel;
            }
        }