static void try_df (const char *name, const char *uuid, const char *dev, int offset) { struct guestfs_statvfs *stat = NULL; guestfs_error_handler_cb old_error_cb; void *old_error_data; if (verbose) fprintf (stderr, "try_df %s %s %d\n", name, dev, offset); /* Try mounting and stating the device. This might reasonably fail, * so don't show errors. */ old_error_cb = guestfs_get_error_handler (g, &old_error_data); guestfs_set_error_handler (g, NULL, NULL); if (guestfs_mount_ro (g, dev, "/") == 0) { stat = guestfs_statvfs (g, "/"); guestfs_umount_all (g); } guestfs_set_error_handler (g, old_error_cb, old_error_data); if (stat) { print_stat (name, uuid, dev, offset, stat); guestfs_free_statvfs (stat); } }
int init_empty (guestfs_h *g) { if (guestfs_blockdev_setrw (g, "/dev/sda") == -1) return -1; if (guestfs_umount_all (g) == -1) return -1; if (guestfs_lvm_remove_all (g) == -1) return -1; return 0; }
/* Since we want this function to be robust against very bad failure * cases (hello, https://bugzilla.kernel.org/show_bug.cgi?id=18792) it * won't exit on guestfs failures. */ int df_on_handle (guestfs_h *g, const char *name, const char *uuid, FILE *fp) { size_t i; CLEANUP_FREE_STRING_LIST char **devices = NULL; CLEANUP_FREE_STRING_LIST char **fses = NULL; if (verbose) fprintf (stderr, "df_on_handle: %s\n", name); devices = guestfs_list_devices (g); if (devices == NULL) return -1; fses = guestfs_list_filesystems (g); if (fses == NULL) return -1; for (i = 0; fses[i] != NULL; i += 2) { if (STRNEQ (fses[i+1], "") && STRNEQ (fses[i+1], "swap") && STRNEQ (fses[i+1], "unknown")) { const char *dev = fses[i]; CLEANUP_FREE_STATVFS struct guestfs_statvfs *stat = NULL; if (verbose) fprintf (stderr, "df_on_handle: %s dev %s\n", name, dev); /* Try mounting and stating the device. This might reasonably * fail, so don't show errors. */ guestfs_push_error_handler (g, NULL, NULL); if (guestfs_mount_ro (g, dev, "/") == 0) { stat = guestfs_statvfs (g, "/"); guestfs_umount_all (g); } guestfs_pop_error_handler (g); if (stat) print_stat (fp, name, uuid, dev, stat); } } return 0; }
static void mount_drive_letter (char drive_letter, const char *root) { char **drives; char *device; size_t i; /* Resolve the drive letter using the drive mappings table. */ drives = guestfs_inspect_get_drive_mappings (g, root); if (drives == NULL || drives[0] == NULL) { fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"), program_name); exit (EXIT_FAILURE); } device = NULL; for (i = 0; drives[i] != NULL; i += 2) { if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') { device = drives[i+1]; break; } } if (device == NULL) { fprintf (stderr, _("%s: drive '%c:' not found.\n"), program_name, drive_letter); exit (EXIT_FAILURE); } /* Unmount current disk and remount device. */ if (guestfs_umount_all (g) == -1) exit (EXIT_FAILURE); if (guestfs_mount_options (g, "", device, "/") == -1) exit (EXIT_FAILURE); for (i = 0; drives[i] != NULL; ++i) free (drives[i]); free (drives); /* Don't need to free (device) because that string was in the * drives array. */ }
static void mount_drive_letter (guestfs_h *g, char drive_letter, const char *root, int readonly) { char *device; size_t i; /* Resolve the drive letter using the drive mappings table. */ CLEANUP_FREE_STRING_LIST char **drives = guestfs_inspect_get_drive_mappings (g, root); if (drives == NULL || drives[0] == NULL) error (EXIT_FAILURE, 0, _("to use Windows drive letters, this must be a Windows guest")); device = NULL; for (i = 0; drives[i] != NULL; i += 2) { if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') { device = drives[i+1]; break; } } if (device == NULL) error (EXIT_FAILURE, 0, _("drive '%c:' not found."), drive_letter); /* Unmount current disk and remount device. */ if (guestfs_umount_all (g) == -1) exit (EXIT_FAILURE); if ((readonly ? guestfs_mount_ro : guestfs_mount) (g, device, "/") == -1) exit (EXIT_FAILURE); /* Don't need to free (device) because that string was in the * drives array. */ }
/* Find out if 'device' contains a filesystem. If it does, add * another entry in g->fses. */ int guestfs_int_check_for_filesystem_on (guestfs_h *g, const char *mountable) { CLEANUP_FREE char *vfs_type = NULL; int is_swap, r; struct inspect_fs *fs; CLEANUP_FREE_INTERNAL_MOUNTABLE struct guestfs_internal_mountable *m = NULL; int whole_device = 0; /* Get vfs-type in order to check if it's a Linux(?) swap device. * If there's an error we should ignore it, so to do that we have to * temporarily replace the error handler with a null one. */ guestfs_push_error_handler (g, NULL, NULL); vfs_type = guestfs_vfs_type (g, mountable); guestfs_pop_error_handler (g); is_swap = vfs_type && STREQ (vfs_type, "swap"); debug (g, "check_for_filesystem_on: %s (%s)", mountable, vfs_type ? vfs_type : "failed to get vfs type"); if (is_swap) { extend_fses (g); fs = &g->fses[g->nr_fses-1]; fs->mountable = safe_strdup (g, mountable); return 0; } m = guestfs_internal_parse_mountable (g, mountable); if (m == NULL) return -1; /* If it's a whole device, see if it is an install ISO. */ if (m->im_type == MOUNTABLE_DEVICE) { whole_device = guestfs_is_whole_device (g, m->im_device); if (whole_device == -1) { return -1; } } if (whole_device) { extend_fses (g); fs = &g->fses[g->nr_fses-1]; r = guestfs_int_check_installer_iso (g, fs, m->im_device); if (r == -1) { /* Fatal error. */ g->nr_fses--; return -1; } if (r > 0) /* Found something. */ return 0; /* Didn't find anything. Fall through ... */ g->nr_fses--; } /* Try mounting the device. As above, ignore errors. */ guestfs_push_error_handler (g, NULL, NULL); if (vfs_type && STREQ (vfs_type, "ufs")) { /* Hack for the *BSDs. */ /* FreeBSD fs is a variant of ufs called ufs2 ... */ r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs", mountable, "/"); if (r == -1) /* while NetBSD and OpenBSD use another variant labeled 44bsd */ r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", mountable, "/"); } else { r = guestfs_mount_ro (g, mountable, "/"); } guestfs_pop_error_handler (g); if (r == -1) return 0; /* Do the rest of the checks. */ r = check_filesystem (g, mountable, m, whole_device); /* Unmount the filesystem. */ if (guestfs_umount_all (g) == -1) return -1; return r; }
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)); }
int main (int argc, char *argv[]) { /* Set global program name that is not polluted with libtool artifacts. */ set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); /* We use random(3) below. */ srandom (time (NULL)); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:b:c:d:e:vVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "backup", 1, 0, 'b' }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "expr", 1, 0, 'e' }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "keys-from-stdin", 0, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; struct drv *drvs = NULL; struct drv *drv; const char *format = NULL; int c; int option_index; char *root, **roots; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } argv[0] = bad_cast (program_name); for (;;) { c = getopt_long (argc, argv, options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: /* options which are long only */ if (STREQ (long_options[option_index].name, "keys-from-stdin")) { keys_from_stdin = 1; } else if (STREQ (long_options[option_index].name, "echo-keys")) { echo_keys = 1; } else if (STREQ (long_options[option_index].name, "format")) { if (!optarg || STREQ (optarg, "")) format = NULL; else format = optarg; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); exit (EXIT_FAILURE); } break; case 'a': OPTION_a; break; case 'b': if (backup_extension) { fprintf (stderr, _("%s: -b option given multiple times\n"), program_name); exit (EXIT_FAILURE); } backup_extension = optarg; break; case 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'e': if (perl_expr) { fprintf (stderr, _("%s: -e option given multiple times\n"), program_name); exit (EXIT_FAILURE); } perl_expr = optarg; break; case 'h': usage (EXIT_SUCCESS); case 'v': OPTION_v; break; case 'V': OPTION_V; break; case 'x': OPTION_x; break; case HELP_OPTION: usage (EXIT_SUCCESS); default: usage (EXIT_FAILURE); } } /* Old-style syntax? There were no -a or -d options in the old * virt-edit which is how we detect this. */ if (drvs == NULL) { /* argc - 1 because last parameter is the single filename. */ while (optind < argc - 1) { if (strchr (argv[optind], '/') || access (argv[optind], F_OK) == 0) { /* simulate -a option */ drv = malloc (sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_a; drv->a.filename = argv[optind]; drv->a.format = NULL; drv->next = drvs; drvs = drv; } else { /* simulate -d option */ drv = malloc (sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_d; drv->d.guest = argv[optind]; drv->next = drvs; drvs = drv; } optind++; } } /* These are really constants, but they have to be variables for the * options parsing code. Assert here that they have known-good * values. */ assert (read_only == 0); assert (inspector == 1); assert (live == 0); /* User must specify at least one filename on the command line. */ if (optind >= argc || argc - optind < 1) usage (EXIT_FAILURE); /* User must have specified some drives. */ if (drvs == NULL) usage (EXIT_FAILURE); /* Add drives. */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); inspect_mount (); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); /* Get root mountpoint. */ roots = guestfs_inspect_get_roots (g); if (!roots) exit (EXIT_FAILURE); /* see fish/inspect.c:inspect_mount */ assert (roots[0] != NULL && roots[1] == NULL); root = roots[0]; free (roots); while (optind < argc) { edit (argv[optind], root); optind++; } free (root); /* Cleanly unmount the disks after editing. */ if (guestfs_umount_all (g) == -1 || guestfs_sync (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); exit (EXIT_SUCCESS); }
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); }