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 do_output_blockdevs (void) { size_t i; CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); for (i = 0; devices[i] != NULL; ++i) { int64_t size = -1; CLEANUP_FREE_STRING_LIST char **parents = NULL; CLEANUP_FREE char *dev; dev = guestfs_canonical_device_name (g, devices[i]); if (!dev) exit (EXIT_FAILURE); if ((columns & COLUMN_SIZE)) { size = guestfs_blockdev_getsize64 (g, devices[i]); if (size == -1) exit (EXIT_FAILURE); } if (is_md (devices[i])) parents = parents_of_md (devices[i]); else parents = no_parents (); write_row (dev, "device", NULL, NULL, -1, size, parents, NULL); } }
/* If the -m option fails on any command, display a useful error * message listing the mountpoints. */ static void display_mountpoints_on_failure (const char *mp_device, const char *user_supplied_options) { CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g); size_t i; if (fses == NULL || fses[0] == NULL) return; fprintf (stderr, _("%s: '%s' could not be mounted.\n"), program_name, mp_device); if (user_supplied_options) fprintf (stderr, _("%s: Check mount(8) man page to ensure options '%s'\n" "%s: are supported by the filesystem that is being mounted.\n"), program_name, user_supplied_options, program_name); fprintf (stderr, _("%s: Did you mean to mount one of these filesystems?\n"), program_name); for (i = 0; fses[i] != NULL; i += 2) { CLEANUP_FREE char *p = guestfs_canonical_device_name (g, fses[i]); fprintf (stderr, "%s: \t%s (%s)\n", program_name, p ? p : fses[i], fses[i+1]); } }
/* This function is called only if the above function was called, * and only after we've printed the prompt in interactive mode. */ void print_inspect_prompt (void) { size_t i; CLEANUP_FREE char *name = NULL; CLEANUP_FREE_STRING_LIST char **mountpoints; name = guestfs_inspect_get_product_name (g, root); if (name && STRNEQ (name, "unknown")) printf (_("Operating system: %s\n"), name); mountpoints = guestfs_inspect_get_mountpoints (g, root); if (mountpoints == NULL) return; /* Sort by key. */ qsort (mountpoints, guestfs___count_strings (mountpoints) / 2, 2 * sizeof (char *), compare_keys); for (i = 0; mountpoints[i] != NULL; i += 2) { /* Try to make the device name canonical for printing, but don't * worry if this fails. */ CLEANUP_FREE char *dev = guestfs_canonical_device_name (g, mountpoints[i+1]); printf (_("%s mounted on %s\n"), dev ? dev : mountpoints[i+1], mountpoints[i]); } }
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 do_output_partitions (void) { size_t i; CLEANUP_FREE_STRING_LIST char **parts = guestfs_list_partitions (g); if (parts == NULL) exit (EXIT_FAILURE); for (i = 0; parts[i] != NULL; ++i) { CLEANUP_FREE char *dev = NULL, *parent_name = NULL, *canonical_name = NULL; const char *parents[2]; int64_t size = -1; int mbr_id = -1; dev = guestfs_canonical_device_name (g, parts[i]); if (!dev) exit (EXIT_FAILURE); if ((columns & COLUMN_SIZE)) { size = guestfs_blockdev_getsize64 (g, parts[i]); if (size == -1) exit (EXIT_FAILURE); } if ((columns & COLUMN_PARENTS)) { parent_name = guestfs_part_to_dev (g, parts[i]); if (parent_name == NULL) exit (EXIT_FAILURE); if ((columns & COLUMN_MBR)) mbr_id = get_mbr_id (parts[i], parent_name); canonical_name = guestfs_canonical_device_name (g, parent_name); if (!canonical_name) exit (EXIT_FAILURE); parents[0] = canonical_name; parents[1] = NULL; } write_row (dev, "partition", NULL, NULL, mbr_id, size, (char **) parents, NULL); } }
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 do_output_pvs (void) { size_t i; struct guestfs_lvm_pv_list *pvs = get_pvs (); for (i = 0; i < pvs->len; ++i) { char uuid[33]; const char *parents[1] = { NULL }; CLEANUP_FREE char *dev = guestfs_canonical_device_name (g, pvs->val[i].pv_name); if (!dev) exit (EXIT_FAILURE); memcpy (uuid, pvs->val[i].pv_uuid, 32); uuid[32] = '\0'; write_row (dev, "pv", NULL, NULL, -1, (int64_t) pvs->val[i].pv_size, (char **) parents, uuid); } }
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)); }
static void do_output_filesystems (void) { size_t i; CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g); if (fses == NULL) exit (EXIT_FAILURE); for (i = 0; fses[i] != NULL; i += 2) { CLEANUP_FREE char *dev = NULL, *vfs_label = NULL, *vfs_uuid = NULL; CLEANUP_FREE_STRING_LIST char **parents = NULL; int64_t size = -1; /* Skip swap and unknown, unless --extra flag was given. */ if (!(output & OUTPUT_FILESYSTEMS_EXTRA) && (STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown"))) continue; dev = guestfs_canonical_device_name (g, fses[i]); if (dev == NULL) exit (EXIT_FAILURE); /* Only bother to look these up if we will be displaying them, * otherwise pass them as NULL. */ if ((columns & COLUMN_VFS_LABEL)) { guestfs_push_error_handler (g, NULL, NULL); vfs_label = guestfs_vfs_label (g, fses[i]); guestfs_pop_error_handler (g); if (vfs_label == NULL) { vfs_label = strdup (""); if (!vfs_label) { perror ("strdup"); exit (EXIT_FAILURE); } } } if ((columns & COLUMN_UUID)) { guestfs_push_error_handler (g, NULL, NULL); vfs_uuid = guestfs_vfs_uuid (g, fses[i]); guestfs_pop_error_handler (g); if (vfs_uuid == NULL) { vfs_uuid = strdup (""); if (!vfs_uuid) { perror ("strdup"); exit (EXIT_FAILURE); } } } if ((columns & COLUMN_SIZE)) { size = guestfs_blockdev_getsize64 (g, fses[i]); if (size == -1) exit (EXIT_FAILURE); } if (is_md (fses[i])) parents = parents_of_md (fses[i]); else parents = no_parents (); write_row (dev, "filesystem", fses[i+1], vfs_label, -1, size, parents, vfs_uuid); } }
void scan (size_t *worst_alignment, const char *prefix) { char **devices, *p; size_t i, j; size_t alignment; uint64_t start; struct guestfs_partition_list *parts; devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); for (i = 0; devices[i] != NULL; ++i) { parts = guestfs_part_list (g, devices[i]); if (parts == NULL) exit (EXIT_FAILURE); /* Canonicalize the name of the device for printing. */ p = guestfs_canonical_device_name (g, devices[i]); if (p == NULL) exit (EXIT_FAILURE); free (devices[i]); devices[i] = p; for (j = 0; j < parts->len; ++j) { /* Start offset of the partition in bytes. */ start = parts->val[j].part_start; if (!quiet) { if (prefix) printf ("%s:", prefix); printf ("%s%d %12" PRIu64 " ", devices[i], (int) parts->val[j].part_num, start); } /* What's the alignment? */ if (start == 0) /* Probably not possible, but anyway. */ alignment = 64; else for (alignment = 0; (start & 1) == 0; alignment++, start /= 2) ; if (!quiet) { if (alignment < 10) printf ("%12" PRIu64 " ", UINT64_C(1) << alignment); else if (alignment < 64) printf ("%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10)); else printf ("- "); } if (alignment < *worst_alignment) *worst_alignment = alignment; if (alignment < 12) { /* Bad in general: < 4K alignment */ if (!quiet) printf ("bad (%s)\n", _("alignment < 4K")); } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */ if (!quiet) printf ("bad (%s)\n", _("alignment < 64K")); } else { if (!quiet) printf ("ok\n"); } } guestfs_free_partition_list (parts); free (devices[i]); } free (devices); }
static int scan (guestfs_h *g, const char *prefix, FILE *fp) { size_t i, j; size_t alignment; uint64_t start; int err; CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g); if (devices == NULL) return -1; for (i = 0; devices[i] != NULL; ++i) { CLEANUP_FREE char *name = NULL; CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *parts = guestfs_part_list (g, devices[i]); if (parts == NULL) return -1; /* Canonicalize the name of the device for printing. */ name = guestfs_canonical_device_name (g, devices[i]); if (name == NULL) return -1; for (j = 0; j < parts->len; ++j) { /* Start offset of the partition in bytes. */ start = parts->val[j].part_start; if (!quiet) { if (prefix) fprintf (fp, "%s:", prefix); fprintf (fp, "%s%d %12" PRIu64 " ", name, (int) parts->val[j].part_num, start); } /* What's the alignment? */ if (start == 0) /* Probably not possible, but anyway. */ alignment = 64; else for (alignment = 0; (start & 1) == 0; alignment++, start /= 2) ; if (!quiet) { if (alignment < 10) fprintf (fp, "%12" PRIu64 " ", UINT64_C(1) << alignment); else if (alignment < 64) fprintf (fp, "%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10)); else fprintf (fp, "- "); } err = pthread_mutex_lock (&worst_alignment_mutex); assert (err == 0); if (alignment < worst_alignment) worst_alignment = alignment; err = pthread_mutex_unlock (&worst_alignment_mutex); assert (err == 0); if (alignment < 12) { /* Bad in general: < 4K alignment */ if (!quiet) fprintf (fp, "bad (%s)\n", _("alignment < 4K")); } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */ if (!quiet) fprintf (fp, "bad (%s)\n", _("alignment < 64K")); } else { if (!quiet) fprintf (fp, "ok\n"); } } } return 0; }