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)); }
/* 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]); } }
/* This function deals with the complexity of adding the domain, * launching the handle, and mounting up filesystems. See * 'examples/inspect-vm.c' to understand how this works. */ static int open_guest (guestfs_h *g, const char *dom, int readonly) { char **roots, *root, **mountpoints; size_t i; /* Use libvirt to find the guest disks and add them to the handle. */ if (guestfs_add_domain (g, dom, GUESTFS_ADD_DOMAIN_READONLY, readonly, -1) == -1) return -1; if (guestfs_launch (g) == -1) return -1; /* Inspect the guest, looking for operating systems. */ roots = guestfs_inspect_os (g); if (roots == NULL) return -1; if (roots[0] == NULL || roots[1] != NULL) { fprintf (stderr, "copy-over: %s: no operating systems or multiple operating systems found\n", dom); return -1; } root = roots[0]; /* Mount up the filesystems (like 'guestfish -i'). */ mountpoints = guestfs_inspect_get_mountpoints (g, root); if (mountpoints == NULL) return -1; qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *), compare_keys_len); for (i = 0; mountpoints[i] != NULL; i += 2) { /* Ignore failures from this call, since bogus entries can * appear in the guest's /etc/fstab. */ (readonly ? guestfs_mount_ro : guestfs_mount) (g, mountpoints[i+1], mountpoints[i]); free (mountpoints[i]); free (mountpoints[i+1]); } free (mountpoints); free (root); free (roots); /* Everything ready, no error. */ return 0; }
void inspect_mount_root (const char *root) { 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, so that we end up * mounting the filesystems in the correct order. */ qsort (mountpoints, guestfs___count_strings (mountpoints) / 2, 2 * sizeof (char *), compare_keys_len); size_t i; size_t mount_errors = 0; for (i = 0; mountpoints[i] != NULL; i += 2) { int r; if (!read_only) r = guestfs_mount (g, mountpoints[i+1], mountpoints[i]); else r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]); if (r == -1) { /* If the "/" filesystem could not be mounted, give up, else * just count the errors and print a warning. */ if (STREQ (mountpoints[i], "/")) exit (EXIT_FAILURE); mount_errors++; } } if (mount_errors) fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"), program_name); }
int main (int argc, char *argv[]) { guestfs_h *g; const char *disk; char **roots, *root, *str, **mountpoints, **lines; size_t i, j; if (argc != 2) { fprintf (stderr, "usage: inspect_vm disk.img\n"); exit (EXIT_FAILURE); } disk = argv[1]; g = guestfs_create (); if (g == NULL) { perror ("failed to create libguestfs handle"); exit (EXIT_FAILURE); } /* Attach the disk image read-only to libguestfs. */ if (guestfs_add_drive_opts (g, disk, /* GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", */ GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) /* this marks end of optional arguments */ == -1) exit (EXIT_FAILURE); /* Run the libguestfs back-end. */ if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Ask libguestfs to inspect for operating systems. */ roots = guestfs_inspect_os (g); if (roots == NULL) exit (EXIT_FAILURE); if (roots[0] == NULL) { fprintf (stderr, "inspect_vm: no operating systems found\n"); exit (EXIT_FAILURE); } for (j = 0; roots[j] != NULL; ++j) { root = roots[j]; printf ("Root device: %s\n", root); /* Print basic information about the operating system. */ str = guestfs_inspect_get_product_name (g, root); if (str) printf (" Product name: %s\n", str); free (str); printf (" Version: %d.%d\n", guestfs_inspect_get_major_version (g, root), guestfs_inspect_get_minor_version (g, root)); str = guestfs_inspect_get_type (g, root); if (str) printf (" Type: %s\n", str); free (str); str = guestfs_inspect_get_distro (g, root); if (str) printf (" Distro: %s\n", str); free (str); /* Mount up the disks, like guestfish -i. * * Sort keys by length, shortest first, so that we end up * mounting the filesystems in the correct order. */ mountpoints = guestfs_inspect_get_mountpoints (g, root); if (mountpoints == NULL) exit (EXIT_FAILURE); qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *), compare_keys_len); for (i = 0; mountpoints[i] != NULL; i += 2) { /* Ignore failures from this call, since bogus entries can * appear in the guest's /etc/fstab. */ guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]); free (mountpoints[i]); free (mountpoints[i+1]); } free (mountpoints); /* If /etc/issue.net file exists, print up to 3 lines. */ if (guestfs_is_file (g, "/etc/issue.net") > 0) { printf ("--- /etc/issue.net ---\n"); lines = guestfs_head_n (g, 3, "/etc/issue.net"); if (lines == NULL) exit (EXIT_FAILURE); for (i = 0; lines[i] != NULL; ++i) { printf ("%s\n", lines[i]); free (lines[i]); } free (lines); } /* Unmount everything. */ if (guestfs_umount_all (g) == -1) exit (EXIT_FAILURE); free (root); } free (roots); guestfs_close (g); exit (EXIT_SUCCESS); }