- /* Ignore certain mountpoints. */
- if (STRPREFIX (mp, "/dev/") ||
- STREQ (mp, "/dev") ||
- STRPREFIX (mp, "/media/") ||
- STRPREFIX (mp, "/proc/") ||
- STREQ (mp, "/proc") ||
- STRPREFIX (mp, "/selinux/") ||
- STREQ (mp, "/selinux") ||
- STRPREFIX (mp, "/sys/") ||
- STREQ (mp, "/sys"))
- return 0;
-
- /* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */
- if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) ||
- STREQ (spec, "/dev/floppy") ||
- STREQ (spec, "/dev/cdrom"))
- return 0;
-
- /* Resolve UUID= and LABEL= to the actual device. */
- char *device = NULL;
- if (STRPREFIX (spec, "UUID="))
- device = guestfs_findfs_uuid (g, &spec[5]);
- else if (STRPREFIX (spec, "LABEL="))
- device = guestfs_findfs_label (g, &spec[6]);
- /* Ignore "/.swap" (Pardus) and pseudo-devices like "tmpfs". */
- else if (STRPREFIX (spec, "/dev/"))
- /* Resolve guest block device names. */
- device = resolve_fstab_device (g, spec);
-
- /* If we haven't resolved the device successfully by this point,
- * we don't care, just ignore it.
- */
- if (device == NULL)
- return 0;
-
- char *mountpoint = safe_strdup (g, mp);
-
- /* Add this to the fstab entry in 'fs'.
- * Note these are further filtered by guestfs_inspect_get_mountpoints
- * and guestfs_inspect_get_filesystems.
- */
- size_t n = fs->nr_fstab + 1;
- struct inspect_fstab_entry *p;
-
- p = realloc (fs->fstab, n * sizeof (struct inspect_fstab_entry));
- if (p == NULL) {
- perrorf (g, "realloc");
- free (device);
- free (mountpoint);
- return -1;
- }
-
- fs->fstab = p;
- fs->nr_fstab = n;
-
- /* These are owned by the handle and freed by guestfs___free_inspect_info. */
- fs->fstab[n-1].device = device;
- fs->fstab[n-1].mountpoint = mountpoint;
-
- if (g->verbose)
- fprintf (stderr, "fstab: device=%s mountpoint=%s\n", device, mountpoint);
-
- return 0;
-}
-
-/* Resolve block device name to the libguestfs device name, eg.
- * /dev/xvdb1 => /dev/vdb1; and /dev/mapper/VG-LV => /dev/VG/LV. This
- * assumes that disks were added in the same order as they appear to
- * the real VM, which is a reasonable assumption to make. Return
- * anything we don't recognize unchanged.
- */
-static char *
-resolve_fstab_device (guestfs_h *g, const char *spec)
-{
- char *a1;
- char *device = NULL;
- char *bsddisk, *bsdslice, *bsdpart;
-
- if (STRPREFIX (spec, "/dev/mapper/")) {
- /* LVM2 does some strange munging on /dev/mapper paths for VGs and
- * LVs which contain '-' character:
- *
- * ><fs> lvcreate LV--test VG--test 32
- * ><fs> debug ls /dev/mapper
- * VG----test-LV----test
- *
- * This makes it impossible to reverse those paths directly, so
- * we have implemented lvm_canonical_lv_name in the daemon.
- */
- device = guestfs_lvm_canonical_lv_name (g, spec);
- }
- else if ((a1 = match1 (g, spec, re_xdev)) != NULL) {
- char **devices = guestfs_list_devices (g);
- if (devices == NULL)
- return NULL;
-
- size_t count;
- for (count = 0; devices[count] != NULL; count++)
- ;
-
- size_t i = a1[0] - 'a'; /* a1[0] is always [a-z] because of regex. */
- if (i < count) {
- size_t len = strlen (devices[i]) + strlen (a1) + 16;
- device = safe_malloc (g, len);
- snprintf (device, len, "%s%s", devices[i], &a1[1]);
- }
-
- free (a1);
- guestfs___free_string_list (devices);
- }
- else if (match3 (g, spec, re_freebsd, &bsddisk, &bsdslice, &bsdpart)) {
- /* FreeBSD disks are organized quite differently. See:
- * http://www.freebsd.org/doc/handbook/disk-organization.html
- * FreeBSD "partitions" are exposed as quasi-extended partitions
- * numbered from 5 in Linux. I have no idea what happens when you
- * have multiple "slices" (the FreeBSD term for MBR partitions).
- */
- int disk = parse_unsigned_int (g, bsddisk);
- int slice = parse_unsigned_int (g, bsdslice);
- int part = bsdpart[0] - 'a' /* counting from 0 */;
- free (bsddisk);
- free (bsdslice);
- free (bsdpart);
-
- if (disk == -1 || disk > 26 ||
- slice <= 0 || slice > 1 /* > 4 .. see comment above */ ||
- part < 0 || part >= 26)
- goto out;
-
- device = safe_asprintf (g, "/dev/sd%c%d", disk + 'a', part + 5);
- }
-
- out:
- /* Didn't match device pattern, return original spec unchanged. */
- if (device == NULL)
- device = safe_strdup (g, spec);
-
- return device;
-}
-
-/* XXX Handling of boot.ini in the Perl version was pretty broken. It
- * essentially didn't do anything for modern Windows guests.
- * Therefore I've omitted all that code.
- */
-static int
-check_windows_root (guestfs_h *g, struct inspect_fs *fs)
-{
- fs->type = OS_TYPE_WINDOWS;
- fs->distro = OS_DISTRO_WINDOWS;
-
- /* Try to find Windows systemroot using some common locations. */
- const char *systemroots[] =
- { "/windows", "/winnt", "/win32", "/win" };
- size_t i;
- char *systemroot = NULL;
- for (i = 0;
- systemroot == NULL && i < sizeof systemroots / sizeof systemroots[0];
- ++i) {
- systemroot = resolve_windows_path_silently (g, systemroots[i]);
- }
-
- if (!systemroot) {
- error (g, _("cannot resolve Windows %%SYSTEMROOT%%"));
- return -1;
- }
-
- if (g->verbose)
- fprintf (stderr, "windows %%SYSTEMROOT%% = %s", systemroot);
-
- /* Freed by guestfs___free_inspect_info. */
- fs->windows_systemroot = systemroot;
-
- if (check_windows_arch (g, fs) == -1)
- return -1;
-
- /* Product name and version. */
- if (check_windows_software_registry (g, fs) == -1)
- return -1;
-
- check_package_format (g, fs);
- check_package_management (g, fs);
-
- /* Hostname. */
- if (check_windows_system_registry (g, fs) == -1)
- return -1;
-
- return 0;
-}
-
-static int
-check_windows_arch (guestfs_h *g, struct inspect_fs *fs)
-{
- size_t len = strlen (fs->windows_systemroot) + 32;
- char cmd_exe[len];
- snprintf (cmd_exe, len, "%s/system32/cmd.exe", fs->windows_systemroot);
-
- char *cmd_exe_path = resolve_windows_path_silently (g, cmd_exe);
- if (!cmd_exe_path)
- return 0;
-
- char *arch = guestfs_file_architecture (g, cmd_exe_path);
- free (cmd_exe_path);
-
- if (arch)
- fs->arch = arch; /* freed by guestfs___free_inspect_info */
-
- return 0;
-}
-
-/* At the moment, pull just the ProductName and version numbers from
- * the registry. In future there is a case for making many more
- * registry fields available to callers.
- */
-static int
-check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
-{
- TMP_TEMPLATE_ON_STACK (software_local);
-
- size_t len = strlen (fs->windows_systemroot) + 64;
- char software[len];
- snprintf (software, len, "%s/system32/config/software",
- fs->windows_systemroot);
-
- char *software_path = resolve_windows_path_silently (g, software);
- if (!software_path)
- /* If the software hive doesn't exist, just accept that we cannot
- * find product_name etc.
- */
- return 0;
-
- int ret = -1;
- hive_h *h = NULL;
- hive_value_h *values = NULL;
-
- if (download_to_tmp (g, software_path, software_local, 100000000) == -1)
- goto out;
-
- h = hivex_open (software_local, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
- if (h == NULL) {
- perrorf (g, "hivex_open");
- goto out;
- }
-
- hive_node_h node = hivex_root (h);
- const char *hivepath[] =
- { "Microsoft", "Windows NT", "CurrentVersion" };
- size_t i;
- for (i = 0;
- node != 0 && i < sizeof hivepath / sizeof hivepath[0];
- ++i) {
- node = hivex_node_get_child (h, node, hivepath[i]);
- }
-
- if (node == 0) {
- perrorf (g, "hivex: cannot locate HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
- goto out;
- }
-
- values = hivex_node_values (h, node);
-
- for (i = 0; values[i] != 0; ++i) {
- char *key = hivex_value_key (h, values[i]);
- if (key == NULL) {
- perrorf (g, "hivex_value_key");
- goto out;
- }
-
- if (STRCASEEQ (key, "ProductName")) {
- fs->product_name = hivex_value_string (h, values[i]);
- if (!fs->product_name) {
- perrorf (g, "hivex_value_string");
- free (key);
- goto out;
- }
- }
- else if (STRCASEEQ (key, "CurrentVersion")) {
- char *version = hivex_value_string (h, values[i]);
- if (!version) {
- perrorf (g, "hivex_value_string");
- free (key);
- goto out;
- }
- char *major, *minor;
- if (match2 (g, version, re_windows_version, &major, &minor)) {
- fs->major_version = parse_unsigned_int (g, major);
- free (major);
- if (fs->major_version == -1) {
- free (minor);
- free (key);
- free (version);
- goto out;
- }
- fs->minor_version = parse_unsigned_int (g, minor);
- free (minor);
- if (fs->minor_version == -1) {
- free (key);
- free (version);
- goto out;
- }
- }
-
- free (version);
- }
-
- free (key);
- }
-
- ret = 0;
-
- out:
- if (h) hivex_close (h);
- free (values);
- free (software_path);
-
- /* Free up the temporary file. */
- unlink (software_local);
-#undef software_local_len
-
- return ret;
-}
-
-static int
-check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
-{
- TMP_TEMPLATE_ON_STACK (system_local);
-
- size_t len = strlen (fs->windows_systemroot) + 64;
- char system[len];
- snprintf (system, len, "%s/system32/config/system",
- fs->windows_systemroot);
-
- char *system_path = resolve_windows_path_silently (g, system);
- if (!system_path)
- /* If the system hive doesn't exist, just accept that we cannot
- * find hostname etc.
- */
- return 0;
-
- int ret = -1;
- hive_h *h = NULL;
- hive_value_h *values = NULL;
-
- if (download_to_tmp (g, system_path, system_local, 100000000) == -1)
- goto out;
-
- h = hivex_open (system_local, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
- if (h == NULL) {
- perrorf (g, "hivex_open");
- goto out;
- }
-
- hive_node_h node = hivex_root (h);
- /* XXX Don't hard-code ControlSet001. The current control set would
- * be another good thing to expose up through the inspection API.
- */
- const char *hivepath[] =
- { "ControlSet001", "Services", "Tcpip", "Parameters" };
- size_t i;
- for (i = 0;
- node != 0 && i < sizeof hivepath / sizeof hivepath[0];
- ++i) {
- node = hivex_node_get_child (h, node, hivepath[i]);
- }
-
- if (node == 0) {
- perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters");
- goto out;
- }
-
- values = hivex_node_values (h, node);
-
- for (i = 0; values[i] != 0; ++i) {
- char *key = hivex_value_key (h, values[i]);
- if (key == NULL) {
- perrorf (g, "hivex_value_key");
- goto out;
- }
-
- if (STRCASEEQ (key, "Hostname")) {
- fs->hostname = hivex_value_string (h, values[i]);
- if (!fs->hostname) {
- perrorf (g, "hivex_value_string");
- free (key);
- goto out;
- }
- }
- /* many other interesting fields here ... */
-
- free (key);
- }
-
- ret = 0;
-
- out:
- if (h) hivex_close (h);
- free (values);
- free (system_path);
-
- /* Free up the temporary file. */
- unlink (system_local);
-#undef system_local_len
-
- return ret;
-}
-
-static char *
-resolve_windows_path_silently (guestfs_h *g, const char *path)
-{
- guestfs_error_handler_cb old_error_cb = g->error_cb;
- g->error_cb = NULL;
- char *ret = guestfs_case_sensitive_path (g, path);
- g->error_cb = old_error_cb;
- return ret;
-}
-
-static int
-extend_fses (guestfs_h *g)
-{
- size_t n = g->nr_fses + 1;
- struct inspect_fs *p;
-
- p = realloc (g->fses, n * sizeof (struct inspect_fs));
- if (p == NULL) {
- perrorf (g, "realloc");
- return -1;
- }
-
- g->fses = p;
- g->nr_fses = n;
-
- memset (&g->fses[n-1], 0, sizeof (struct inspect_fs));
-
- return 0;
-}
-
-/* Parse small, unsigned ints, as used in version numbers. */
-static int
-parse_unsigned_int (guestfs_h *g, const char *str)
-{
- long ret;
- int r = xstrtol (str, NULL, 10, &ret, "");
- if (r != LONGINT_OK) {
- error (g, _("could not parse integer in version number: %s"), str);
- return -1;
- }
- 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:
- case OS_DISTRO_MANDRIVA:
- fs->package_format = OS_PACKAGE_FORMAT_RPM;
- break;
-
- case OS_DISTRO_DEBIAN:
- case OS_DISTRO_UBUNTU:
- case OS_DISTRO_LINUX_MINT:
- 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:
- case OS_DISTRO_LINUX_MINT:
- 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_MANDRIVA:
- fs->package_management = OS_PACKAGE_MANAGEMENT_URPMI;
- 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)
-{
- if (g->nr_fses == 0) {
- error (g, _("no inspection data: call guestfs_inspect_os first"));
- return NULL;
- }
-
- size_t i;
- struct inspect_fs *fs;
- for (i = 0; i < g->nr_fses; ++i) {
- fs = &g->fses[i];
- if (fs->is_root && STREQ (root, fs->device))
- return fs;
- }
-
- error (g, _("%s: root device not found: only call this function with a root device previously returned by guestfs_inspect_os"),
- root);
- return NULL;
-}
-
-char **
-guestfs__inspect_get_roots (guestfs_h *g)
-{
- /* NB. Doesn't matter if g->nr_fses == 0. We just return an empty
- * list in this case.
- */
-
- size_t i;
- size_t count = 0;
- for (i = 0; i < g->nr_fses; ++i)
- if (g->fses[i].is_root)
- count++;
-
- char **ret = calloc (count+1, sizeof (char *));
- if (ret == NULL) {
- perrorf (g, "calloc");
- return NULL;
- }
-
- count = 0;
- for (i = 0; i < g->nr_fses; ++i) {
- if (g->fses[i].is_root) {
- ret[count] = safe_strdup (g, g->fses[i].device);
- count++;
- }
- }
- ret[count] = NULL;
-
- return ret;
-}
-
-char *
-guestfs__inspect_get_type (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- char *ret;
- switch (fs->type) {
- case OS_TYPE_LINUX: ret = safe_strdup (g, "linux"); break;
- case OS_TYPE_WINDOWS: ret = safe_strdup (g, "windows"); break;
- case OS_TYPE_FREEBSD: ret = safe_strdup (g, "freebsd"); break;
- case OS_TYPE_UNKNOWN: default: ret = safe_strdup (g, "unknown"); break;
- }
-
- return ret;
-}
-
-char *
-guestfs__inspect_get_arch (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- return safe_strdup (g, fs->arch ? : "unknown");
-}
-
-char *
-guestfs__inspect_get_distro (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- char *ret;
- switch (fs->distro) {
- case OS_DISTRO_ARCHLINUX: ret = safe_strdup (g, "archlinux"); break;
- case OS_DISTRO_DEBIAN: ret = safe_strdup (g, "debian"); break;
- case OS_DISTRO_FEDORA: ret = safe_strdup (g, "fedora"); break;
- case OS_DISTRO_GENTOO: ret = safe_strdup (g, "gentoo"); break;
- case OS_DISTRO_LINUX_MINT: ret = safe_strdup (g, "linuxmint"); break;
- case OS_DISTRO_MANDRIVA: ret = safe_strdup (g, "mandriva"); break;
- case OS_DISTRO_MEEGO: ret = safe_strdup (g, "meego"); break;
- case OS_DISTRO_PARDUS: ret = safe_strdup (g, "pardus"); break;
- case OS_DISTRO_REDHAT_BASED: ret = safe_strdup (g, "redhat-based"); break;
- case OS_DISTRO_RHEL: ret = safe_strdup (g, "rhel"); break;
- case OS_DISTRO_WINDOWS: ret = safe_strdup (g, "windows"); break;
- case OS_DISTRO_UBUNTU: ret = safe_strdup (g, "ubuntu"); break;
- case OS_DISTRO_UNKNOWN: default: ret = safe_strdup (g, "unknown"); break;
- }
-
- return ret;
-}
-
-int
-guestfs__inspect_get_major_version (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return -1;
-
- return fs->major_version;
-}
-
-int
-guestfs__inspect_get_minor_version (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return -1;
-
- return fs->minor_version;
-}
-
-char *
-guestfs__inspect_get_product_name (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- return safe_strdup (g, fs->product_name ? : "unknown");
-}
-
-char *
-guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- if (!fs->windows_systemroot) {
- error (g, _("not a Windows guest, or systemroot could not be determined"));
- return NULL;
- }
-
- return safe_strdup (g, fs->windows_systemroot);
-}
-
-char **
-guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- char **ret;
-
- /* If no fstab information (Windows) return just the root. */
- if (fs->nr_fstab == 0) {
- ret = calloc (3, sizeof (char *));
- ret[0] = safe_strdup (g, "/");
- ret[1] = safe_strdup (g, root);
- ret[2] = NULL;
- return ret;
- }
-
-#define CRITERION fs->fstab[i].mountpoint[0] == '/'
- size_t i, count = 0;
- for (i = 0; i < fs->nr_fstab; ++i)
- if (CRITERION)
- count++;
-
- /* Hashtables have 2N+1 entries. */
- ret = calloc (2*count+1, sizeof (char *));
- if (ret == NULL) {
- perrorf (g, "calloc");
- return NULL;
- }
-
- count = 0;
- for (i = 0; i < fs->nr_fstab; ++i)
- if (CRITERION) {
- ret[2*count] = safe_strdup (g, fs->fstab[i].mountpoint);
- ret[2*count+1] = safe_strdup (g, fs->fstab[i].device);
- count++;
- }
-#undef CRITERION
-
- return ret;
-}
-
-char **
-guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- char **ret;
-
- /* If no fstab information (Windows) return just the root. */
- if (fs->nr_fstab == 0) {
- ret = calloc (2, sizeof (char *));
- ret[0] = safe_strdup (g, root);
- ret[1] = NULL;
- return ret;
- }
-
- ret = calloc (fs->nr_fstab + 1, sizeof (char *));
- if (ret == NULL) {
- perrorf (g, "calloc");
- return NULL;
- }
-
- size_t i;
- for (i = 0; i < fs->nr_fstab; ++i)
- ret[i] = safe_strdup (g, fs->fstab[i].device);
-
- 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_URPMI: ret = safe_strdup (g, "urpmi"); break;
- case OS_PACKAGE_MANAGEMENT_UNKNOWN:
- default:
- ret = safe_strdup (g, "unknown");
- break;
- }
-
- return ret;
-}
-
-char *
-guestfs__inspect_get_hostname (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);
- if (!fs)
- return NULL;
-
- return safe_strdup (g, fs->hostname ? : "unknown");
-}
-
-static struct guestfs_application_list *list_applications_rpm (guestfs_h *g, struct inspect_fs *fs);
-static struct guestfs_application_list *list_applications_deb (guestfs_h *g, struct inspect_fs *fs);
-static struct guestfs_application_list *list_applications_windows (guestfs_h *g, struct inspect_fs *fs);
-static void add_application (guestfs_h *g, struct guestfs_application_list *, const char *name, const char *display_name, int32_t epoch, const char *version, const char *release, const char *install_path, const char *publisher, const char *url, const char *description);
-static void sort_applications (struct guestfs_application_list *);
-
-/* Unlike the simple inspect-get-* calls, this one assumes that the
- * disks are mounted up, and reads files from the mounted disks.
- */
-struct guestfs_application_list *
-guestfs__inspect_list_applications (guestfs_h *g, const char *root)
-{
- struct inspect_fs *fs = search_for_root (g, root);