static void output (char **roots) { xmlOutputBufferPtr ob = xmlOutputBufferCreateFd (1, NULL); if (ob == NULL) { fprintf (stderr, _("%s: xmlOutputBufferCreateFd: failed to open stdout\n"), guestfs_int_program_name); exit (EXIT_FAILURE); } /* 'ob' is freed when 'xo' is freed.. */ CLEANUP_XMLFREETEXTWRITER xmlTextWriterPtr xo = xmlNewTextWriter (ob); if (xo == NULL) { fprintf (stderr, _("%s: xmlNewTextWriter: failed to create libxml2 writer\n"), guestfs_int_program_name); exit (EXIT_FAILURE); } /* Pretty-print the output. */ XMLERROR (-1, xmlTextWriterSetIndent (xo, 1)); XMLERROR (-1, xmlTextWriterSetIndentString (xo, BAD_CAST " ")); XMLERROR (-1, xmlTextWriterStartDocument (xo, NULL, NULL, NULL)); output_roots (xo, roots); XMLERROR (-1, xmlTextWriterEndDocument (xo)); }
static void output_roots (xmlTextWriterPtr xo, char **roots) { size_t i; XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "operatingsystems")); for (i = 0; roots[i] != NULL; ++i) output_root (xo, roots[i]); XMLERROR (-1, xmlTextWriterEndElement (xo)); }
static void output_filesystems (xmlTextWriterPtr xo, char *root) { char *str; size_t i; CLEANUP_FREE_STRING_LIST char **filesystems = guestfs_inspect_get_filesystems (g, root); if (filesystems == NULL) exit (EXIT_FAILURE); /* Sort by name so the output is stable. */ qsort (filesystems, guestfs_int_count_strings (filesystems), sizeof (char *), compare_keys); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystems")); for (i = 0; filesystems[i] != NULL; ++i) { str = guestfs_canonical_device_name (g, filesystems[i]); if (!str) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystem")); XMLERROR (-1, xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST str)); free (str); guestfs_push_error_handler (g, NULL, NULL); str = guestfs_vfs_type (g, filesystems[i]); if (str && str[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "type", BAD_CAST str)); free (str); str = guestfs_vfs_label (g, filesystems[i]); if (str && str[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "label", BAD_CAST str)); free (str); str = guestfs_vfs_uuid (g, filesystems[i]); if (str && str[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "uuid", BAD_CAST str)); free (str); guestfs_pop_error_handler (g); XMLERROR (-1, xmlTextWriterEndElement (xo)); } XMLERROR (-1, xmlTextWriterEndElement (xo)); }
static void output_mountpoints (xmlTextWriterPtr xo, char *root) { size_t i; CLEANUP_FREE_STRING_LIST char **mountpoints = guestfs_inspect_get_mountpoints (g, root); if (mountpoints == NULL) exit (EXIT_FAILURE); /* Sort by key length, shortest key first, and then name, so the * output is stable. */ qsort (mountpoints, guestfs_int_count_strings (mountpoints) / 2, 2 * sizeof (char *), compare_keys_len); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "mountpoints")); for (i = 0; mountpoints[i] != NULL; i += 2) { CLEANUP_FREE char *p = guestfs_canonical_device_name (g, mountpoints[i+1]); if (!p) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "mountpoint")); XMLERROR (-1, xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST p)); XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST mountpoints[i])); XMLERROR (-1, xmlTextWriterEndElement (xo)); } XMLERROR (-1, xmlTextWriterEndElement (xo)); }
static void output (char **roots) { xmlOutputBufferPtr ob = xmlOutputBufferCreateFd (1, NULL); if (ob == NULL) error (EXIT_FAILURE, 0, _("xmlOutputBufferCreateFd: failed to open stdout")); /* 'ob' is freed when 'xo' is freed.. */ CLEANUP_XMLFREETEXTWRITER xmlTextWriterPtr xo = xmlNewTextWriter (ob); if (xo == NULL) error (EXIT_FAILURE, 0, _("xmlNewTextWriter: failed to create libxml2 writer")); /* Pretty-print the output. */ XMLERROR (-1, xmlTextWriterSetIndent (xo, 1)); XMLERROR (-1, xmlTextWriterSetIndentString (xo, BAD_CAST " ")); XMLERROR (-1, xmlTextWriterStartDocument (xo, NULL, NULL, NULL)); output_roots (xo, roots); XMLERROR (-1, xmlTextWriterEndDocument (xo)); }
static void output_drive_mappings (xmlTextWriterPtr xo, char *root) { CLEANUP_FREE_STRING_LIST char **drive_mappings = NULL; char *str; size_t i; guestfs_push_error_handler (g, NULL, NULL); drive_mappings = guestfs_inspect_get_drive_mappings (g, root); guestfs_pop_error_handler (g); if (drive_mappings == NULL) return; if (drive_mappings[0] == NULL) return; /* Sort by key. */ qsort (drive_mappings, guestfs_int_count_strings (drive_mappings) / 2, 2 * sizeof (char *), compare_keys_nocase); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "drive_mappings")); for (i = 0; drive_mappings[i] != NULL; i += 2) { str = guestfs_canonical_device_name (g, drive_mappings[i+1]); if (!str) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "drive_mapping")); XMLERROR (-1, xmlTextWriterWriteAttribute (xo, BAD_CAST "name", BAD_CAST drive_mappings[i])); XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST str)); XMLERROR (-1, xmlTextWriterEndElement (xo)); free (str); } XMLERROR (-1, xmlTextWriterEndElement (xo)); }
static void output_applications (xmlTextWriterPtr xo, char *root) { size_t i; /* This returns an empty list if we simply couldn't determine the * applications, so if it returns NULL then it's a real error. */ CLEANUP_FREE_APPLICATION2_LIST struct guestfs_application2_list *apps = guestfs_inspect_list_applications2 (g, root); if (apps == NULL) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "applications")); for (i = 0; i < apps->len; ++i) { XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "application")); assert (apps->val[i].app2_name && apps->val[i].app2_name[0]); XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "name", BAD_CAST apps->val[i].app2_name)); if (apps->val[i].app2_display_name && apps->val[i].app2_display_name[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "display_name", BAD_CAST apps->val[i].app2_display_name)); if (apps->val[i].app2_epoch != 0) { char buf[32]; snprintf (buf, sizeof buf, "%d", apps->val[i].app2_epoch); XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "epoch", BAD_CAST buf)); } if (apps->val[i].app2_version && apps->val[i].app2_version[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "version", BAD_CAST apps->val[i].app2_version)); if (apps->val[i].app2_release && apps->val[i].app2_release[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "release", BAD_CAST apps->val[i].app2_release)); if (apps->val[i].app2_arch && apps->val[i].app2_arch[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "arch", BAD_CAST apps->val[i].app2_arch)); if (apps->val[i].app2_install_path && apps->val[i].app2_install_path[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "install_path", BAD_CAST apps->val[i].app2_install_path)); if (apps->val[i].app2_publisher && apps->val[i].app2_publisher[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "publisher", BAD_CAST apps->val[i].app2_publisher)); if (apps->val[i].app2_url && apps->val[i].app2_url[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "url", BAD_CAST apps->val[i].app2_url)); if (apps->val[i].app2_source_package && apps->val[i].app2_source_package[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "source_package", BAD_CAST apps->val[i].app2_source_package)); if (apps->val[i].app2_summary && apps->val[i].app2_summary[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "summary", BAD_CAST apps->val[i].app2_summary)); if (apps->val[i].app2_description && apps->val[i].app2_description[0]) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "description", BAD_CAST apps->val[i].app2_description)); XMLERROR (-1, xmlTextWriterEndElement (xo)); } XMLERROR (-1, xmlTextWriterEndElement (xo)); }
static void output_root (xmlTextWriterPtr xo, char *root) { char *str; int i, r; char buf[32]; char *canonical_root; size_t size; XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "operatingsystem")); canonical_root = guestfs_canonical_device_name (g, root); if (canonical_root == NULL) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "root", BAD_CAST canonical_root)); free (canonical_root); str = guestfs_inspect_get_type (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "name", BAD_CAST str)); free (str); str = guestfs_inspect_get_arch (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "arch", BAD_CAST str)); free (str); str = guestfs_inspect_get_distro (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "distro", BAD_CAST str)); free (str); str = guestfs_inspect_get_product_name (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "product_name", BAD_CAST str)); free (str); str = guestfs_inspect_get_product_variant (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "product_variant", BAD_CAST str)); free (str); i = guestfs_inspect_get_major_version (g, root); snprintf (buf, sizeof buf, "%d", i); XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "major_version", BAD_CAST buf)); i = guestfs_inspect_get_minor_version (g, root); snprintf (buf, sizeof buf, "%d", i); XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "minor_version", BAD_CAST buf)); str = guestfs_inspect_get_package_format (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "package_format", BAD_CAST str)); free (str); str = guestfs_inspect_get_package_management (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "package_management", BAD_CAST str)); free (str); /* inspect-get-windows-systemroot will fail with non-windows guests, * or if the systemroot could not be determined for a windows guest. * Disable error output around this call. */ guestfs_push_error_handler (g, NULL, NULL); str = guestfs_inspect_get_windows_systemroot (g, root); if (str) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "windows_systemroot", BAD_CAST str)); free (str); str = guestfs_inspect_get_windows_current_control_set (g, root); if (str) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "windows_current_control_set", BAD_CAST str)); free (str); guestfs_pop_error_handler (g); str = guestfs_inspect_get_hostname (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "hostname", BAD_CAST str)); free (str); str = guestfs_inspect_get_format (g, root); if (!str) exit (EXIT_FAILURE); if (STRNEQ (str, "unknown")) XMLERROR (-1, xmlTextWriterWriteElement (xo, BAD_CAST "format", BAD_CAST str)); free (str); r = guestfs_inspect_is_live (g, root); if (r > 0) { XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "live")); XMLERROR (-1, xmlTextWriterEndElement (xo)); } r = guestfs_inspect_is_netinst (g, root); if (r > 0) { XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "netinst")); XMLERROR (-1, xmlTextWriterEndElement (xo)); } r = guestfs_inspect_is_multipart (g, root); if (r > 0) { XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "multipart")); XMLERROR (-1, xmlTextWriterEndElement (xo)); } output_mountpoints (xo, root); output_filesystems (xo, root); output_drive_mappings (xo, root); /* We need to mount everything up in order to read out the list of * applications and the icon, ie. everything below this point. */ inspect_mount_root (g, root); output_applications (xo, root); /* Don't return favicon. RHEL 7 and Fedora have crappy 16x16 * favicons in the base distro. */ str = guestfs_inspect_get_icon (g, root, &size, GUESTFS_INSPECT_GET_ICON_FAVICON, 0, -1); if (!str) exit (EXIT_FAILURE); if (size > 0) { XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "icon")); XMLERROR (-1, xmlTextWriterWriteBase64 (xo, str, 0, size)); XMLERROR (-1, xmlTextWriterEndElement (xo)); } /* Note we must free (str) even if size == 0, because that indicates * there was no icon. */ free (str); /* Unmount (see inspect_mount_root above). */ if (guestfs_umount_all (g) == -1) exit (EXIT_FAILURE); XMLERROR (-1, xmlTextWriterEndElement (xo)); }