From 3fd2b9d0b6d2bac5e9267fbcf1556f459d7313fe Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Fri, 12 Nov 2010 12:29:14 +0000 Subject: [PATCH] New APIs: inspect-get-package-format, inspect-get-package-management. This APIs reimplement some parts of virt-inspector in C. --- generator/generator_actions.ml | 46 +++++++++++++ inspector/virt-inspector | 64 +++++------------- src/guestfs-internal.h | 21 ++++++ src/inspect.c | 146 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+), 49 deletions(-) diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 12fda29..8cb93aa 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -1119,6 +1119,52 @@ The optional parameters are passed directly through to C."); *) + ("inspect_get_package_format", (RString "packageformat", [Device "root"], []), -1, [], + [], + "get package format used by the operating system", + "\ +This function should only be called with a root device string +as returned by C. + +This function and C return +the package format and package management tool used by the +inspected operating system. For example for Fedora these +functions would return C (package format) and +C (package management). + +This returns the string C if we could not determine the +package format I if the operating system does not have +a real packaging system (eg. Windows). + +Possible strings include: C, C, C, C, C. +Future versions of libguestfs may return other strings. + +Please read L for more details."); + + ("inspect_get_package_management", (RString "packagemanagement", [Device "root"], []), -1, [], + [], + "get package management tool used by the operating system", + "\ +This function should only be called with a root device string +as returned by C. + +C and this function return +the package format and package management tool used by the +inspected operating system. For example for Fedora these +functions would return C (package format) and +C (package management). + +This returns the string C if we could not determine the +package management tool I if the operating system does not have +a real packaging system (eg. Windows). + +Possible strings include: C, C, +C (for all Debian derivatives), +C, C, C. +Future versions of libguestfs may return other strings. + +Please read L for more details."); + ] (* daemon_functions are any functions which cause some action diff --git a/inspector/virt-inspector b/inspector/virt-inspector index 9e12dc8..ce9ac0e 100755 --- a/inspector/virt-inspector +++ b/inspector/virt-inspector @@ -200,17 +200,17 @@ foreach $root (@roots) { # Basic OS fields. $xml->dataElement (root => canonicalize ($root)); - my ($s, $distro, $major_version); + my $s; $s = $g->inspect_get_type ($root); $xml->dataElement (name => $s) if $s ne "unknown"; $s = $g->inspect_get_arch ($root); $xml->dataElement (arch => $s) if $s ne "unknown"; - $distro = $g->inspect_get_distro ($root); - $xml->dataElement (distro => $distro) if $distro ne "unknown"; + $s = $g->inspect_get_distro ($root); + $xml->dataElement (distro => $s) if $s ne "unknown"; $s = $g->inspect_get_product_name ($root); $xml->dataElement (product_name => $s) if $s ne "unknown"; - $major_version = $g->inspect_get_major_version ($root); - $xml->dataElement (major_version => $major_version); + $s = $g->inspect_get_major_version ($root); + $xml->dataElement (major_version => $s); $s = $g->inspect_get_minor_version ($root); $xml->dataElement (minor_version => $s); @@ -226,7 +226,7 @@ foreach $root (@roots) { output_filesystems ($root); # Package format / management and applications. - output_applications ($root, $distro, $major_version); + output_applications ($root); $xml->endTag("operatingsystem"); @@ -370,58 +370,24 @@ sub output_applications { local $_; my $root = shift; - my $distro = shift; - my $major_version = shift; # Based on the distro, take a guess at the package format # and package management. my ($package_format, $package_management); - if (defined $distro) { - if ($distro eq "archlinux") { - $package_format = "pacman"; - $package_management = "pacman"; - } - elsif ($distro eq "debian" || $distro eq "ubuntu") { - $package_format = "deb"; - $package_management = "apt"; - } - elsif ($distro eq "fedora" || $distro eq "meego") { - $package_format = "rpm"; - $package_management = "yum"; - } - elsif ($distro eq "gentoo") { - $package_format = "ebuild"; - $package_management = "portage"; - } - elsif ($distro eq "pardus") { - $package_format = "pisi"; - $package_management = "pisi"; - } - elsif ($distro =~ /redhat/ || $distro =~ /rhel/) { - if ($major_version >= 5) { - $package_format = "rpm"; - $package_management = "yum"; - } else { - $package_format = "rpm"; - $package_management = "up2date"; - } - } - # else unknown. - } + $package_format = $g->inspect_get_package_format ($root); + $package_management = $g->inspect_get_package_management ($root); $xml->dataElement (package_format => $package_format) - if defined $package_format; + if $package_format ne "unknown"; $xml->dataElement (package_management => $package_management) - if defined $package_management; + if $package_management ne "unknown"; # Do we know how to get a list of applications? - if (defined $package_format) { - if ($package_format eq "rpm") { - output_applications_rpm ($root); - } - elsif ($package_format eq "deb") { - output_applications_deb ($root); - } + if ($package_format eq "rpm") { + output_applications_rpm ($root); + } + elsif ($package_format eq "deb") { + output_applications_deb ($root); } } diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 6dbbeec..65ca4f2 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -181,6 +181,25 @@ enum inspect_os_distro { OS_DISTRO_MEEGO, }; +enum inspect_os_package_format { + OS_PACKAGE_FORMAT_UNKNOWN = 0, + OS_PACKAGE_FORMAT_RPM, + OS_PACKAGE_FORMAT_DEB, + OS_PACKAGE_FORMAT_PACMAN, + OS_PACKAGE_FORMAT_EBUILD, + OS_PACKAGE_FORMAT_PISI +}; + +enum inspect_os_package_management { + OS_PACKAGE_MANAGEMENT_UNKNOWN = 0, + OS_PACKAGE_MANAGEMENT_YUM, + OS_PACKAGE_MANAGEMENT_UP2DATE, + OS_PACKAGE_MANAGEMENT_APT, + OS_PACKAGE_MANAGEMENT_PACMAN, + OS_PACKAGE_MANAGEMENT_PORTAGE, + OS_PACKAGE_MANAGEMENT_PISI, +}; + struct inspect_fs { int is_root; char *device; @@ -189,6 +208,8 @@ struct inspect_fs { enum inspect_fs_content content; enum inspect_os_type type; enum inspect_os_distro distro; + enum inspect_os_package_format package_format; + enum inspect_os_package_management package_management; char *product_name; int major_version; int minor_version; diff --git a/src/inspect.c b/src/inspect.c index 2b61a75..3b2720c 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -197,6 +197,8 @@ static int parse_unsigned_int (guestfs_h *g, const char *str); static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, const char *spec, const char *mp); static char *resolve_fstab_device (guestfs_h *g, const char *spec); +static void check_package_format (guestfs_h *g, struct inspect_fs *fs); +static void check_package_management (guestfs_h *g, struct inspect_fs *fs); static int check_for_filesystem_on (guestfs_h *g, const char *device) @@ -516,6 +518,10 @@ check_linux_root (guestfs_h *g, struct inspect_fs *fs) skip_release_checks:; + /* If distro test above was successful, work out the package format. */ + check_package_format (g, fs); + check_package_management (g, fs); + /* Determine the architecture. */ const char *binaries[] = { "/bin/bash", "/bin/ls", "/bin/echo", "/bin/rm", "/bin/sh" }; @@ -776,6 +782,9 @@ check_windows_root (guestfs_h *g, struct inspect_fs *fs) if (check_windows_registry (g, fs) == -1) return -1; + check_package_format (g, fs); + check_package_management (g, fs); + return 0; } @@ -972,6 +981,84 @@ parse_unsigned_int (guestfs_h *g, const char *str) return ret; } +/* At the moment, package format and package management is just a + * simple function of the distro and major_version fields, so these + * can never return an error. We might be cleverer in future. + */ +static void +check_package_format (guestfs_h *g, struct inspect_fs *fs) +{ + switch (fs->distro) { + case OS_DISTRO_FEDORA: + case OS_DISTRO_MEEGO: + case OS_DISTRO_REDHAT_BASED: + case OS_DISTRO_RHEL: + fs->package_format = OS_PACKAGE_FORMAT_RPM; + break; + + case OS_DISTRO_DEBIAN: + case OS_DISTRO_UBUNTU: + fs->package_format = OS_PACKAGE_FORMAT_DEB; + break; + + case OS_DISTRO_ARCHLINUX: + fs->package_format = OS_PACKAGE_FORMAT_PACMAN; + break; + case OS_DISTRO_GENTOO: + fs->package_format = OS_PACKAGE_FORMAT_EBUILD; + break; + case OS_DISTRO_PARDUS: + fs->package_format = OS_PACKAGE_FORMAT_PISI; + break; + + case OS_DISTRO_WINDOWS: + case OS_DISTRO_UNKNOWN: + default: + fs->package_format = OS_PACKAGE_FORMAT_UNKNOWN; + break; + } +} + +static void +check_package_management (guestfs_h *g, struct inspect_fs *fs) +{ + switch (fs->distro) { + case OS_DISTRO_FEDORA: + case OS_DISTRO_MEEGO: + fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; + break; + + case OS_DISTRO_REDHAT_BASED: + case OS_DISTRO_RHEL: + if (fs->major_version >= 5) + fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; + else + fs->package_management = OS_PACKAGE_MANAGEMENT_UP2DATE; + break; + + case OS_DISTRO_DEBIAN: + case OS_DISTRO_UBUNTU: + fs->package_management = OS_PACKAGE_MANAGEMENT_APT; + break; + + case OS_DISTRO_ARCHLINUX: + fs->package_management = OS_PACKAGE_MANAGEMENT_PACMAN; + break; + case OS_DISTRO_GENTOO: + fs->package_management = OS_PACKAGE_MANAGEMENT_PORTAGE; + break; + case OS_DISTRO_PARDUS: + fs->package_management = OS_PACKAGE_MANAGEMENT_PISI; + break; + + case OS_DISTRO_WINDOWS: + case OS_DISTRO_UNKNOWN: + default: + fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN; + break; + } +} + static struct inspect_fs * search_for_root (guestfs_h *g, const char *root) { @@ -1194,6 +1281,53 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root) return ret; } +char * +guestfs__inspect_get_package_format (guestfs_h *g, const char *root) +{ + struct inspect_fs *fs = search_for_root (g, root); + if (!fs) + return NULL; + + char *ret; + switch (fs->package_format) { + case OS_PACKAGE_FORMAT_RPM: ret = safe_strdup (g, "rpm"); break; + case OS_PACKAGE_FORMAT_DEB: ret = safe_strdup (g, "deb"); break; + case OS_PACKAGE_FORMAT_PACMAN: ret = safe_strdup (g, "pacman"); break; + case OS_PACKAGE_FORMAT_EBUILD: ret = safe_strdup (g, "ebuild"); break; + case OS_PACKAGE_FORMAT_PISI: ret = safe_strdup (g, "pisi"); break; + case OS_PACKAGE_FORMAT_UNKNOWN: + default: + ret = safe_strdup (g, "unknown"); + break; + } + + return ret; +} + +char * +guestfs__inspect_get_package_management (guestfs_h *g, const char *root) +{ + struct inspect_fs *fs = search_for_root (g, root); + if (!fs) + return NULL; + + char *ret; + switch (fs->package_management) { + case OS_PACKAGE_MANAGEMENT_YUM: ret = safe_strdup (g, "yum"); break; + case OS_PACKAGE_MANAGEMENT_UP2DATE: ret = safe_strdup (g, "up2date"); break; + case OS_PACKAGE_MANAGEMENT_APT: ret = safe_strdup (g, "apt"); break; + case OS_PACKAGE_MANAGEMENT_PACMAN: ret = safe_strdup (g, "pacman"); break; + case OS_PACKAGE_MANAGEMENT_PORTAGE: ret = safe_strdup (g, "portage"); break; + case OS_PACKAGE_MANAGEMENT_PISI: ret = safe_strdup (g, "pisi"); break; + case OS_PACKAGE_MANAGEMENT_UNKNOWN: + default: + ret = safe_strdup (g, "unknown"); + break; + } + + return ret; +} + #else /* no PCRE or hivex at compile time */ /* XXX These functions should be in an optgroup. */ @@ -1268,6 +1402,18 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root) NOT_IMPL(NULL); } +char * +guestfs__inspect_get_package_format (guestfs_h *g, const char *root) +{ + NOT_IMPL(NULL); +} + +char * +guestfs__inspect_get_package_management (guestfs_h *g, const char *root) +{ + NOT_IMPL(NULL); +} + #endif /* no PCRE or hivex at compile time */ void -- 1.8.3.1