static void run_test (void) { guestfs_h *g; size_t i; printf ("Warming up the libguestfs cache ...\n"); for (i = 0; i < NR_WARMUP_PASSES; ++i) { g = create_handle (); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); } printf ("Running the tests in %d passes ...\n", NR_TEST_PASSES); for (i = 0; i < NR_TEST_PASSES; ++i) { g = create_handle (); set_up_event_handlers (g, i); start_libvirt_thread (i); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); stop_libvirt_thread (); printf (" pass %zu: %zu events collected in %" PRIi64 " ns\n", i+1, pass_data[i].nr_events, pass_data[i].elapsed_ns); } if (verbose) dump_pass_data (); printf ("Analyzing the results ...\n"); check_pass_data (); construct_timeline (); analyze_timeline (); if (verbose) dump_timeline (); printf ("\n"); g = create_handle (); test_info (g, NR_TEST_PASSES); guestfs_close (g); printf ("\n"); print_analysis (); printf ("\n"); printf ("Longest activities:\n"); printf ("\n"); print_longest_to_shortest (); free_pass_data (); free_final_timeline (); }
/* Perform 'df' operation on the domain(s) given in the list. */ static void multi_df (struct domain *domains, size_t n, size_t *errors_r) { size_t i; size_t nd; size_t count; int r; char **devices; char **domain_devices; /* Add all the disks to the handle (since they were added in reverse * order, we must add them here in reverse too). */ for (i = 0, count = 0; i < n; ++i) count += add_disks_to_handle_reverse (domains[i].disks, errors_r); if (count == 0) return; /* Launch the handle. */ if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); for (i = 0, nd = 0; i < n; ++i) { /* Find out how many non-failed disks this domain has. */ count = count_non_failed_disks (domains[i].disks); if (count == 0) continue; /* Duplicate the devices into a separate list for convenience. * Note this doesn't duplicate the strings themselves. */ domain_devices = duplicate_first_n (&devices[nd], count); r = df_on_handle (domains[i].name, domains[i].uuid, domain_devices, nd); nd += count; free (domain_devices); /* Something broke in df_on_handle. Give up on the remaining * devices for this handle, but keep going on the next handle. */ if (r == -1) { (*errors_r)++; break; } } for (i = 0; devices[i] != NULL; ++i) free (devices[i]); free (devices); /* Reset the handle. */ reset_guestfs_handle (); }
/* Perform 'df' operation on the domain(s) given in the list. */ static void multi_df (struct domain *domains, size_t n) { size_t i; size_t nd; int r; char **devices; /* Add all the disks to the handle (since they were added in reverse * order, we must add them here in reverse too). */ for (i = 0; i < n; ++i) add_disks_to_handle_reverse (domains[i].disks); /* Launch the handle. */ if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); /* Check the number of disks we think we added is the same as the * number of devices returned by libguestfs. */ nd = 0; for (i = 0; i < n; ++i) nd += domains[i].nr_disks; assert (nd == count_strings (devices)); nd = 0; for (i = 0; i < n; ++i) { /* So that &devices[nd] is a NULL-terminated list of strings. */ char *p = devices[nd + domains[i].nr_disks]; devices[nd + domains[i].nr_disks] = NULL; r = df_on_handle (domains[i].name, domains[i].uuid, &devices[nd], nd); /* Restore devices to original. */ devices[nd + domains[i].nr_disks] = p; nd += domains[i].nr_disks; /* Something broke in df_on_handle. Give up on the remaining * devices for this handle, but keep going on the next handle. */ if (r == -1) break; } for (i = 0; devices[i] != NULL; ++i) free (devices[i]); free (devices); /* Reset the handle. */ reset_guestfs_handle (); }
int main (int argc, char *argv[]) { guestfs_h *g; int r; char *data; size_t i, size; if (test_start_nbdkit ("-n", NBDKIT_PLUGIN ("file"), "file=file-data", NULL) == -1) exit (EXIT_FAILURE); g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); exit (EXIT_FAILURE); } /* Using any exportname causes qemu to use the newstyle protocol. */ r = guestfs_add_drive_opts (g, "/" /* exportname */, GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd", GUESTFS_ADD_DRIVE_OPTS_SERVER, server, -1); if (r == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Check the data in the file is \x01-\x08 repeated 512 times. */ data = guestfs_pread_device (g, "/dev/sda", 8 * 512, 0, &size); if (!data) exit (EXIT_FAILURE); if (size != 8 * 512) { fprintf (stderr, "%s FAILED: unexpected size (actual: %zu, expected: 512)\n", program_name, size); exit (EXIT_FAILURE); } for (i = 0; i < 512 * 8; i += 8) { if (data[i] != 1 || data[i+1] != 2 || data[i+2] != 3 || data[i+3] != 4 || data[i+4] != 5 || data[i+5] != 6 || data[i+6] != 7 || data[i+7] != 8) { fprintf (stderr, "%s FAILED: unexpected data returned at offset %zu\n", program_name, i); exit (EXIT_FAILURE); } } free (data); guestfs_close (g); exit (EXIT_SUCCESS); }
/* Create the handle, with attached disks. */ static guestfs_h * create_handle (void) { guestfs_h *g; g = guestfs_create (); if (g == NULL) { printf ("FAIL: guestfs_create\n"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 524288000, -1) == -1) { printf ("FAIL: guestfs_add_drive_scratch\n"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 52428800, -1) == -1) { printf ("FAIL: guestfs_add_drive_scratch\n"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 10485760, -1) == -1) { printf ("FAIL: guestfs_add_drive_scratch\n"); exit (EXIT_FAILURE); } if (guestfs_add_drive_ro (g, "../data/test.iso") == -1) { printf ("FAIL: guestfs_add_drive_ro ../data/test.iso\n"); exit (EXIT_FAILURE); } /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */ alarm (600); if (guestfs_launch (g) == -1) { printf ("FAIL: guestfs_launch\n"); exit (EXIT_FAILURE); } /* Cancel previous alarm. */ alarm (0); /* Create ext2 filesystem on /dev/sdb1 partition. */ if (guestfs_part_disk (g, "/dev/sdb", "mbr") == -1) { printf ("FAIL: guestfs_part_disk\n"); exit (EXIT_FAILURE); } if (guestfs_mkfs (g, "ext2", "/dev/sdb1") == -1) { printf ("FAIL: guestfs_mkfs (/dev/sdb1)\n"); exit (EXIT_FAILURE); } return g; }
/* 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; }
int main (int argc, char *argv[]) { char *str; guestfs_h *g; char tmp[] = "/tmp/charsetXXXXXX"; int fd; size_t i; struct filesystem *fs; /* Allow this test to be skipped. */ str = getenv ("SKIP_TEST_CHARSET_FIDELITY"); if (str && STREQ (str, "1")) { printf ("%s: test skipped because environment variable is set.\n", argv[0]); exit (77); } g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, 0, "failed to create handle"); fd = mkstemp (tmp); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp"); if (ftruncate (fd, 1024 * 1024 * 1024) == -1) error (EXIT_FAILURE, errno, "ftruncate: %s", tmp); if (close (fd) == -1) error (EXIT_FAILURE, errno, "close: %s", tmp); if (guestfs_add_drive_opts (g, tmp, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); for (i = 0; i < sizeof filesystems / sizeof filesystems[0]; ++i) { fs = &filesystems[i]; test_filesystem (g, fs); } guestfs_close (g); unlink (tmp); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; size_t i; int lengths[] = { 0, 1, 1024, GUESTFS_ERROR_LEN-2, GUESTFS_ERROR_LEN-1, GUESTFS_ERROR_LEN, GUESTFS_ERROR_LEN+1, GUESTFS_ERROR_LEN+2, GUESTFS_ERROR_LEN*2, -1 }; char len_s[64]; char *args[2]; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); exit (EXIT_FAILURE); } if (guestfs_add_drive (g, "/dev/null") == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_push_error_handler (g, NULL, NULL); for (i = 0; lengths[i] != -1; ++i) { snprintf (len_s, sizeof len_s, "%d", lengths[i]); args[0] = len_s; args[1] = NULL; if (guestfs_debug (g, "error", args) != NULL) { fprintf (stderr, "%s: unexpected return value from 'debug error'\n", argv[0]); exit (EXIT_FAILURE); } /* EROFS is a magic value returned by debug_error in the daemon. */ if (guestfs_last_errno (g) != EROFS) { fprintf (stderr, "%s: unexpected error from 'debug error': %s\n", argv[0], guestfs_last_error (g)); exit (EXIT_FAILURE); } /* else OK */ } guestfs_pop_error_handler (g); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; const char *filename = "test.log"; FILE *debugfp; debugfp = fopen (filename, "w"); if (debugfp == NULL) { perror (filename); exit (EXIT_FAILURE); } g = guestfs_create (); if (g == NULL) { fprintf (stderr, "failed to create handle\n"); exit (EXIT_FAILURE); } if (guestfs_set_event_callback (g, debug_to_file, GUESTFS_EVENT_LIBRARY | GUESTFS_EVENT_APPLIANCE | GUESTFS_EVENT_WARNING | GUESTFS_EVENT_TRACE, 0, debugfp) == -1) exit (EXIT_FAILURE); if (guestfs_set_verbose (g, 1) == -1) exit (EXIT_FAILURE); if (guestfs_set_trace (g, 1) == -1) exit (EXIT_FAILURE); if (guestfs_add_drive_opts (g, "/dev/null", GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); exit (EXIT_SUCCESS); }
static int scan_work (guestfs_h *g, size_t i, FILE *fp) { struct guestfs___add_libvirt_dom_argv optargs; optargs.bitmask = GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK | GUESTFS___ADD_LIBVIRT_DOM_READONLYDISK_BITMASK; optargs.readonly = 1; optargs.readonlydisk = "read"; if (guestfs___add_libvirt_dom (g, domains[i].dom, &optargs) == -1) return -1; if (guestfs_launch (g) == -1) return -1; return scan (g, !uuid ? domains[i].name : domains[i].uuid, fp); }
int df_work (guestfs_h *g, size_t i, FILE *fp) { struct guestfs_add_libvirt_dom_argv optargs; optargs.bitmask = GUESTFS_ADD_LIBVIRT_DOM_READONLY_BITMASK | GUESTFS_ADD_LIBVIRT_DOM_READONLYDISK_BITMASK; optargs.readonly = 1; optargs.readonlydisk = "read"; /* Traditionally we have ignored errors from adding disks in virt-df. */ if (guestfs_add_libvirt_dom_argv (g, domains[i].dom, &optargs) == -1) return 0; if (guestfs_launch (g) == -1) return -1; return df_on_handle (g, domains[i].name, domains[i].uuid, fp); }
int main (int argc, char *argv[]) { char *str; guestfs_h *g; size_t i; struct filesystem *fs; /* Allow this test to be skipped. */ str = getenv (ourenvvar); if (str && STREQ (str, "1")) { printf ("%s: test skipped because environment variable is set.\n", program_name); exit (77); } g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, 0, "failed to create handle"); if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); for (i = 0; i < sizeof filesystems / sizeof filesystems[0]; ++i) { fs = &filesystems[i]; test_filesystem (g, fs); } guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; struct guestfs_internal_mountable *mountable; const char *devices[] = { "/dev/VG/LV", NULL }; const char *feature[] = { "btrfs", NULL }; g = guestfs_create (); if (g == NULL) { perror ("could not create handle"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1) { error: guestfs_close (g); exit (EXIT_FAILURE); } if (guestfs_launch (g) == -1) goto error; if (!guestfs_feature_available (g, (char **) feature)) { printf ("skipping test because btrfs is not available\n"); guestfs_close (g); exit (77); } if (!guestfs_filesystem_available (g, "btrfs")) { printf ("skipping test because btrfs filesystem is not available\n"); guestfs_close (g); exit (77); } if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) goto error; if (guestfs_pvcreate (g, "/dev/sda1") == -1) goto error; const char *pvs[] = { "/dev/sda1", NULL }; if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) goto error; if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) goto error; if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) goto error; if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) goto error; if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) goto error; mountable = guestfs_internal_parse_mountable (g, "/dev/VG/LV"); if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_DEVICE || STRNEQ ("/dev/VG/LV", mountable->im_device)) { fprintf (stderr, "incorrectly parsed /dev/VG/LV: im_device=%s\n", mountable->im_device); goto error; } guestfs_free_internal_mountable (mountable); mountable = guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv"); if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_BTRFSVOL || STRNEQ ("/dev/VG/LV", mountable->im_device) || STRNEQ ("sv", mountable->im_volume)) { fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv: im_device=%s, im_volume=%s\n", mountable->im_device, mountable->im_volume); goto error; } guestfs_free_internal_mountable (mountable); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; int fd, r; char tempdir[] = "/tmp/mlXXXXXX"; pid_t pid; char *shell, *p; if (argc != 2) { usage (); exit (EXIT_FAILURE); } printf ("\n" "This is the 'mount-local' demonstration program. Follow the\n" "instructions on screen.\n" "\n" "Creating and formatting the disk image, please wait a moment ...\n"); fflush (stdout); /* Create the output disk image: raw sparse. */ fd = open (argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644); if (fd == -1) { perror (argv[1]); exit (EXIT_FAILURE); } if (ftruncate (fd, SIZE_MB * 1024 * 1024) == -1) { perror ("truncate"); close (fd); exit (EXIT_FAILURE); } if (close (fd) == -1) { perror ("close"); exit (EXIT_FAILURE); } /* Guestfs handle. */ g = guestfs_create (); if (g == NULL) { perror ("could not create libguestfs handle"); exit (EXIT_FAILURE); } /* Create the disk image and format it with a partition and a filesystem. */ if (guestfs_add_drive_opts (g, argv[1], GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); if (guestfs_mkfs (g, "ext2", "/dev/sda1") == -1) exit (EXIT_FAILURE); /* Mount the empty filesystem. */ if (guestfs_mount_options (g, MOUNT_OPTIONS, "/dev/sda1", "/") == -1) exit (EXIT_FAILURE); /* Create a file in the new filesystem. */ if (guestfs_touch (g, "/PUT_FILES_AND_DIRECTORIES_HERE") == -1) exit (EXIT_FAILURE); /* Create a temporary mount directory. */ if (mkdtemp (tempdir) == NULL) { perror ("mkdtemp"); exit (EXIT_FAILURE); } /* Mount the filesystem. */ if (guestfs_mount_local (g, tempdir, -1) == -1) exit (EXIT_FAILURE); /* Fork the shell for the user. */ pid = fork (); if (pid == -1) { perror ("fork"); exit (EXIT_FAILURE); } if (pid == 0) { /* Child. */ if (chdir (tempdir) == -1) { perror (tempdir); _exit (EXIT_FAILURE); } printf ("\n" "The *current directory* is a FUSE filesystem backed by the disk\n" "image which is managed by libguestfs. Any files or directories\n" "you copy into here (up to %d MB) will be saved into the disk\n" "image. You can also delete files, create certain special files\n" "and so on.\n" "\n" "When you have finished adding files, hit ^D or type 'exit' to\n" "exit the shell and return to the mount-local program.\n" "\n", SIZE_MB); shell = getenv ("SHELL"); if (!shell) r = system ("/bin/sh"); else { /* Set a magic prompt. We only know how to do this for bash. */ p = strrchr (shell, '/'); if (p && strcmp (p+1, "bash") == 0) { size_t len = 64 + strlen (shell); char buf[len]; snprintf (buf, len, "PS1='mount-local-shell> ' %s --norc -i", shell); r = system (buf); } else r = system (shell); } if (r == -1) { fprintf (stderr, "error: failed to run sub-shell (%s) " "(is $SHELL set correctly?)\n", shell); //FALLTHROUGH } chdir ("/"); guestfs_umount_local (g, GUESTFS_UMOUNT_LOCAL_RETRY, 1, -1); _exit (EXIT_SUCCESS); } /* Note that we are *not* waiting for the child yet. We want to * run the FUSE code in parallel with the subshell. */ /* We're going to hide libguestfs errors here, but in a real program * you would probably want to log them somewhere. */ guestfs_push_error_handler (g, NULL, NULL); /* Now run the FUSE thread. */ if (guestfs_mount_local_run (g) == -1) exit (EXIT_FAILURE); guestfs_pop_error_handler (g); waitpid (pid, NULL, 0); /* Shutdown the handle explicitly so write errors can be detected. */ if (guestfs_shutdown (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); printf ("\n" "Any files or directories that you copied in have been saved into\n" "the disk image called '%s'.\n" "\n" "Try opening the disk image with guestfish to see those files:\n" "\n" " guestfish -a %s -m /dev/sda1\n" "\n", argv[1], argv[1]); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:vVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "keys-from-stdin", 0, 0, 0 }, { "long-options", 0, 0, 0 }, { "short-options", 0, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { "xpath", 1, 0, 0 }, { 0, 0, 0, 0 } }; struct drv *drvs = NULL; struct drv *drv; const char *format = NULL; bool format_consumed = true; int c; int option_index; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } 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, "long-options")) display_long_options (long_options); else if (STREQ (long_options[option_index].name, "short-options")) display_short_options (options); else 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")) { OPTION_format; } else if (STREQ (long_options[option_index].name, "xpath")) { xpath = optarg; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), guestfs_int_program_name, long_options[option_index].name, option_index); exit (EXIT_FAILURE); } break; case 'a': OPTION_a; break; case 'c': OPTION_c; break; case 'd': OPTION_d; break; 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-inspector which is how we detect this. */ if (drvs == NULL) { while (optind < argc) { if (strchr (argv[optind], '/') || access (argv[optind], F_OK) == 0) { /* simulate -a option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("calloc"); exit (EXIT_FAILURE); } drv->type = drv_a; drv->a.filename = strdup (argv[optind]); if (!drv->a.filename) { perror ("strdup"); exit (EXIT_FAILURE); } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("calloc"); 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 == 1); assert (inspector == 1); assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) usage (EXIT_FAILURE); CHECK_OPTION_format_consumed; /* XPath is modal: no drives should be specified. There must be * one extra parameter on the command line. */ if (xpath) { if (drvs != NULL) { fprintf (stderr, _("%s: cannot use --xpath together with other options.\n"), guestfs_int_program_name); exit (EXIT_FAILURE); } do_xpath (xpath); exit (EXIT_SUCCESS); } /* User must have specified some drives. */ if (drvs == NULL) usage (EXIT_FAILURE); /* Add drives, inspect and mount. Note that inspector is always true, * and there is no -m option. */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); /* NB. Can't call inspect_mount () here (ie. normal processing of * the -i option) because it can only handle a single root. So we * use low-level APIs. */ inspect_do_decrypt (g); { CLEANUP_FREE_STRING_LIST char **roots = guestfs_inspect_os (g); if (roots == NULL) { fprintf (stderr, _("%s: no operating system could be detected inside this disk image.\n\nThis may be because the file is not a disk image, or is not a virtual machine\nimage, or because the OS type is not understood by libguestfs.\n\nNOTE for Red Hat Enterprise Linux 6 users: for Windows guest support you must\ninstall the separate libguestfs-winsupport package.\n\nIf you feel this is an error, please file a bug report including as much\ninformation about the disk image as possible.\n"), guestfs_int_program_name); exit (EXIT_FAILURE); } output (roots); } guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:vVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "keys-from-stdin", 0, 0, 0 }, { "long-options", 0, 0, 0 }, { "short-options", 0, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; struct drv *drvs = NULL; const char *format = NULL; bool format_consumed = true; int c; int r; int option_index; g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, errno, "guestfs_create"); 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, "long-options")) display_long_options (long_options); else if (STREQ (long_options[option_index].name, "short-options")) display_short_options (options); else 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")) { OPTION_format; } else error (EXIT_FAILURE, 0, _("unknown long option: %s (%d)"), long_options[option_index].name, option_index); break; case 'a': OPTION_a; break; case 'c': OPTION_c; break; case 'd': OPTION_d; break; 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); } } /* 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 == 1); assert (inspector == 1); assert (live == 0); /* User must not specify more arguments on the command line. */ if (optind != argc) { fprintf (stderr, _("%s: error: extra argument '%s' on command line.\n" "Make sure to specify the argument for --format " "like '--format=%s'.\n"), guestfs_int_program_name, argv[optind], argv[optind]); usage (EXIT_FAILURE); } CHECK_OPTION_format_consumed; /* User must have specified some drives. */ if (drvs == NULL) { fprintf (stderr, _("%s: error: you must specify at least one -a or -d option.\n"), guestfs_int_program_name); usage (EXIT_FAILURE); } /* Add drives, inspect and mount. Note that inspector is always true, * and there is no -m option. */ 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); r = do_log (); guestfs_close (g); exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
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); }
/* Worker thread. */ static void * start_thread (void *thread_data_vp) { struct thread_data *thread_data = thread_data_vp; int quit = 0; int err; size_t i; guestfs_h *g; unsigned errors = 0; char id[64]; for (;;) { CLEANUP_FREE char *log_file = NULL; CLEANUP_FCLOSE FILE *log_fp = NULL; /* Take the next process. */ err = pthread_mutex_lock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_lock: %s", guestfs_int_program_name, strerror (err)); goto error; } i = n; if (i > 0) { printf ("%zu to go ... \r", n); fflush (stdout); n--; } else quit = 1; err = pthread_mutex_unlock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_unlock: %s", guestfs_int_program_name, strerror (err)); goto error; } if (quit) /* Work finished. */ break; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); errors++; if (!ignore_errors) goto error; } /* Only if using --log, set up a callback. See examples/debug-logging.c */ if (log_template != NULL) { size_t j, k; log_file = malloc (log_file_size + 1); if (log_file == NULL) abort (); for (j = 0, k = 0; j < strlen (log_template); ++j) { if (log_template[j] == '%') { snprintf (&log_file[k], log_file_size - k, "%zu", i); k += strlen (&log_file[k]); } else log_file[k++] = log_template[j]; } log_file[k] = '\0'; log_fp = fopen (log_file, "w"); if (log_fp == NULL) { perror (log_file); abort (); } guestfs_set_event_callback (g, message_callback, event_bitmask, 0, log_fp); } snprintf (id, sizeof id, "%zu", i); guestfs_set_identifier (g, id); guestfs_set_trace (g, trace); guestfs_set_verbose (g, verbose); if (guestfs_add_drive_ro (g, "/dev/null") == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_launch (g) == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_shutdown (g) == -1) { errors++; if (!ignore_errors) goto error; } guestfs_close (g); } if (errors > 0) { fprintf (stderr, "%s: thread %d: %u errors were ignored\n", guestfs_int_program_name, thread_data->thread_num, errors); goto error; } thread_data->r = 0; return &thread_data->r; error: thread_data->r = -1; return &thread_data->r; }
int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:hiP:vVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "connect", 1, 0, 'c' }, { "csv", 0, 0, 0 }, { "domain", 1, 0, 'd' }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "human-readable", 0, 0, 'h' }, { "inodes", 0, 0, 'i' }, { "long-options", 0, 0, 0 }, { "one-per-guest", 0, 0, 0 }, { "short-options", 0, 0, 0 }, { "uuid", 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; bool format_consumed = true; int c; int option_index; size_t max_threads = 0; int err; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } 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, "long-options")) display_long_options (long_options); else if (STREQ (long_options[option_index].name, "short-options")) display_short_options (options); else if (STREQ (long_options[option_index].name, "format")) { OPTION_format; } else if (STREQ (long_options[option_index].name, "csv")) { csv = 1; } else if (STREQ (long_options[option_index].name, "one-per-guest")) { /* nothing - left for backwards compatibility */ } else if (STREQ (long_options[option_index].name, "uuid")) { uuid = 1; } 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 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'h': human = 1; break; case 'i': inodes = 1; break; case 'P': if (sscanf (optarg, "%zu", &max_threads) != 1) { fprintf (stderr, _("%s: -P option is not numeric\n"), program_name); exit (EXIT_FAILURE); } break; 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-df which is how we detect this. */ if (drvs == NULL) { while (optind < argc) { if (strchr (argv[optind], '/') || access (argv[optind], F_OK) == 0) { /* simulate -a option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_a; drv->a.filename = strdup (argv[optind]); if (!drv->a.filename) { perror ("strdup"); exit (EXIT_FAILURE); } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ drv = calloc (1, 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 == 1); assert (inspector == 0); assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) usage (EXIT_FAILURE); CHECK_OPTION_format_consumed; /* -h and --csv doesn't make sense. Spreadsheets will corrupt these * fields. (RHBZ#600977). */ if (human && csv) { fprintf (stderr, _("%s: you cannot use -h and --csv options together.\n"), program_name); exit (EXIT_FAILURE); } /* virt-df has two modes. If the user didn't specify any drives, * then we do the df on every libvirt guest. That's the if-clause * below. If the user specified domains/drives, then we assume they * belong to a single guest. That's the else-clause below. */ if (drvs == NULL) { #if defined(HAVE_LIBVIRT) get_all_libvirt_domains (libvirt_uri); print_title (); err = start_threads (max_threads, g, df_work); free_domains (); #else fprintf (stderr, _("%s: compiled without support for libvirt.\n"), program_name); exit (EXIT_FAILURE); #endif } else { /* Single guest. */ CLEANUP_FREE char *name = NULL; /* Add domains/drives from the command line (for a single guest). */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); print_title (); /* Synthesize a display name. */ name = make_display_name (drvs); /* XXX regression: in the Perl version we cached the UUID from the * libvirt domain handle so it was available to us here. In this * version the libvirt domain handle is hidden inside * guestfs_add_domain so the UUID is not available easily for * single '-d' command-line options. */ err = df_on_handle (g, name, NULL, stdout); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); } guestfs_close (g); exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
static int do_make_fs (const char *input, const char *output_str) { const char *dev, *options; CLEANUP_UNLINK_FREE char *output = NULL; uint64_t estimate, size; struct guestfs_disk_create_argv optargs; CLEANUP_FREE char *ifmt = NULL; CLEANUP_FREE char *ifile = NULL; pid_t pid; int status, fd; /* Use of CLEANUP_UNLINK_FREE *output ensures the output file is * deleted unless we successfully reach the end of this function. */ output = strdup (output_str); if (output == NULL) { perror ("strdup"); return -1; } /* Input. What is it? Estimate how much space it will need. */ if (estimate_input (input, &estimate, &ifmt) == -1) return -1; if (verbose) { fprintf (stderr, "input format = %s\n", ifmt); fprintf (stderr, "estimate = %" PRIu64 " bytes " "(%" PRIu64 " 1K blocks, %" PRIu64 " 4K blocks)\n", estimate, estimate / 1024, estimate / 4096); } estimate += 256 * 1024; /* For superblocks &c. */ if (STRPREFIX (type, "ext") && type[3] >= '3') { /* For ext3+, add some more for the journal. */ estimate += 1024 * 1024; } else if (STREQ (type, "ntfs")) { estimate += 4 * 1024 * 1024; /* NTFS journal. */ } else if (STREQ (type, "btrfs")) { /* For BTRFS, the minimum metadata allocation is 256MB, with data * additional to that. Note that we disable data and metadata * duplication below. */ estimate += 256 * 1024 * 1024; } /* Add 10%, see above. */ estimate *= 1.10; /* Calculate the output size. */ if (size_str == NULL) size = estimate; else if (parse_size (size_str, estimate, &size) == -1) return -1; /* Create the output disk. */ optargs.bitmask = 0; if (STREQ (format, "qcow2")) { optargs.bitmask |= GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK; optargs.preallocation = "metadata"; } if (guestfs_disk_create_argv (g, output, format, size, &optargs) == -1) return -1; if (guestfs_add_drive_opts (g, output, GUESTFS_ADD_DRIVE_OPTS_FORMAT, format, -1) == -1) return -1; if (guestfs_launch (g) == -1) return -1; if (check_ntfs_available () == -1) return -1; /* Partition the disk. */ dev = "/dev/sda"; if (partition) { int mbr_id = 0; if (STREQ (partition, "")) partition = "mbr"; if (guestfs_part_disk (g, dev, partition) == -1) return -1; dev = "/dev/sda1"; /* Set the partition type byte if it's MBR and the filesystem type * is one that we know about. */ if (STREQ (partition, "mbr") || STREQ (partition, "msdos")) { if (STREQ (type, "msdos")) /* According to Wikipedia. However I have not actually tried this. */ mbr_id = 0x1; else if (STREQ (type, "vfat") || STREQ (type, "fat")) mbr_id = 0xb; else if (STREQ (type, "ntfs")) mbr_id = 0x7; else if (STRPREFIX (type, "ext")) mbr_id = 0x83; else if (STREQ (type, "minix")) mbr_id = 0x81; } if (mbr_id != 0) { if (guestfs_part_set_mbr_id (g, "/dev/sda", 1, mbr_id) == -1) return -1; } } if (verbose) fprintf (stderr, "creating %s filesystem on %s ...\n", type, dev); /* Create the filesystem. */ if (STRNEQ (type, "btrfs")) { int r; struct guestfs_mkfs_opts_argv optargs = { .bitmask = 0 }; if (label) { optargs.label = label; optargs.bitmask |= GUESTFS_MKFS_OPTS_LABEL_BITMASK; } guestfs_push_error_handler (g, NULL, NULL); r = guestfs_mkfs_opts_argv (g, type, dev, &optargs); guestfs_pop_error_handler (g); if (r == -1) { /* Provide more guidance in the error message (RHBZ#823883). */ fprintf (stderr, "%s: 'mkfs' (create filesystem) operation failed: %s\n", guestfs_int_program_name, guestfs_last_error (g)); if (STREQ (type, "fat")) fprintf (stderr, "Instead of 'fat', try 'vfat' (long filenames) or 'msdos' (short filenames).\n"); else fprintf (stderr, "Is '%s' a correct filesystem type?\n", type); return -1; } } else {
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); }
int main (int argc, char *argv[]) { guestfs_h *g; int r, err; struct guestfs_stat *stat; g = guestfs_create (); if (g == NULL) { fprintf (stderr, "failed to create handle\n"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 524288000, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); if (guestfs_mkfs (g, "ext2", "/dev/sda1") == -1) exit (EXIT_FAILURE); /* Mount read-only, and check that errno == EROFS is passed back when * we create a file. */ if (guestfs_mount_ro (g, "/dev/sda1", "/") == -1) exit (EXIT_FAILURE); r = guestfs_touch (g, "/test"); if (r != -1) { fprintf (stderr, "guestfs_touch: expected error for read-only filesystem\n"); exit (EXIT_FAILURE); } err = guestfs_last_errno (g); if (err != EROFS) { fprintf (stderr, "guestfs_touch: expected errno == EROFS, but got %d\n", err); exit (EXIT_FAILURE); } if (guestfs_umount (g, "/") == -1) exit (EXIT_FAILURE); /* Mount it writable and test some other errors. */ if (guestfs_mount (g, "/dev/sda1", "/") == -1) exit (EXIT_FAILURE); stat = guestfs_lstat (g, "/nosuchfile"); if (stat != NULL) { fprintf (stderr, "guestfs_lstat: expected error for missing file\n"); exit (EXIT_FAILURE); } err = guestfs_last_errno (g); if (err != ENOENT) { fprintf (stderr, "guestfs_lstat: expected errno == ENOENT, but got %d\n", err); exit (EXIT_FAILURE); } if (guestfs_touch (g, "/test") == -1) exit (EXIT_FAILURE); r = guestfs_mkdir (g, "/test"); if (r != -1) { fprintf (stderr, "guestfs_mkdir: expected error for file which exists\n"); exit (EXIT_FAILURE); } err = guestfs_last_errno (g); if (err != EEXIST) { fprintf (stderr, "guestfs_mkdir: expected errno == EEXIST, but got %d\n", err); exit (EXIT_FAILURE); } guestfs_close (g); exit (EXIT_SUCCESS); }
static void test_block_device (void) { int fd; char tmpfile[] = "/tmp/speedtestXXXXXX"; CLEANUP_FREE char **devices = NULL; char *r; const char *argv[4]; int t = max_time_override > 0 ? max_time_override : TEST_BLOCK_DEVICE_TIME; char tbuf[64]; int64_t bytes_written, bytes_read; if (!block_device_write && !block_device_read) return; snprintf (tbuf, sizeof tbuf, "%d", t); g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); /* Create a fully allocated backing file. Note we are not testing * the speed of allocation on the host. */ fd = mkstemp (tmpfile); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp: %s", tmpfile); close (fd); if (guestfs_disk_create (g, tmpfile, "raw", INT64_C (1024*1024*1024), GUESTFS_DISK_CREATE_PREALLOCATION, "full", -1) == -1) exit (EXIT_FAILURE); if (guestfs_add_drive (g, tmpfile) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); if (devices[0] == NULL) { fprintf (stderr, "%s: expected guestfs_list_devices to return at least 1 device\n", guestfs_int_program_name); exit (EXIT_FAILURE); } if (block_device_write) { /* Test write speed. */ argv[0] = devices[0]; argv[1] = "w"; argv[2] = tbuf; argv[3] = NULL; r = guestfs_debug (g, "device_speed", (char **) argv); if (r == NULL) exit (EXIT_FAILURE); if (sscanf (r, "%" SCNi64, &bytes_written) != 1) { fprintf (stderr, "%s: could not parse device_speed output\n", guestfs_int_program_name); exit (EXIT_FAILURE); } print_rate ("block device writes:", bytes_written / t); } if (block_device_read) { /* Test read speed. */ argv[0] = devices[0]; argv[1] = "r"; argv[2] = tbuf; argv[3] = NULL; r = guestfs_debug (g, "device_speed", (char **) argv); if (r == NULL) exit (EXIT_FAILURE); if (sscanf (r, "%" SCNi64, &bytes_read) != 1) { fprintf (stderr, "%s: could not parse device_speed output\n", guestfs_int_program_name); exit (EXIT_FAILURE); } print_rate ("block device reads:", bytes_read / t); } if (guestfs_shutdown (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); /* Remove temporary file. */ unlink (tmpfile); }
static void test_virtio_serial (void) { int fd, r, eh; char tmpfile[] = "/tmp/speedtestXXXXXX"; struct sigaction sa, old_sa; if (!virtio_serial_upload && !virtio_serial_download) return; /* Create a sparse file. We could upload from /dev/zero, but we * won't get progress messages because libguestfs tests if the * source file is a regular file. */ fd = mkstemp (tmpfile); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp: %s", tmpfile); if (ftruncate (fd, TEST_SERIAL_MAX_SIZE) == -1) error (EXIT_FAILURE, errno, "ftruncate"); if (close (fd) == -1) error (EXIT_FAILURE, errno, "close"); g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); if (guestfs_add_drive_scratch (g, INT64_C (100*1024*1024), -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Make and mount a filesystem which will be used by the download test. */ if (guestfs_mkfs (g, "ext4", "/dev/sda") == -1) exit (EXIT_FAILURE); if (guestfs_mount (g, "/dev/sda", "/") == -1) exit (EXIT_FAILURE); /* Time out the upload after TEST_SERIAL_MAX_TIME seconds have passed. */ memset (&sa, 0, sizeof sa); sa.sa_handler = stop_transfer; sa.sa_flags = SA_RESTART; sigaction (SIGALRM, &sa, &old_sa); /* Get progress messages, which will tell us how much data has been * transferred. */ eh = guestfs_set_event_callback (g, progress_cb, GUESTFS_EVENT_PROGRESS, 0, NULL); if (eh == -1) exit (EXIT_FAILURE); if (virtio_serial_upload) { gettimeofday (&start, NULL); rate = -1; operation = "upload"; alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME); /* For the upload test, upload the sparse file to /dev/null in the * appliance. Hopefully this is mostly testing just virtio-serial. */ guestfs_push_error_handler (g, NULL, NULL); r = guestfs_upload (g, tmpfile, "/dev/null"); alarm (0); unlink (tmpfile); guestfs_pop_error_handler (g); /* It's possible that the upload will finish before the alarm fires, * or that the upload will be stopped by the alarm. */ if (r == -1 && guestfs_last_errno (g) != EINTR) { fprintf (stderr, "%s: expecting upload command to return EINTR\n%s\n", guestfs_int_program_name, guestfs_last_error (g)); exit (EXIT_FAILURE); } if (rate == -1) { rate_error: fprintf (stderr, "%s: internal error: progress callback was not called! (r=%d, errno=%d)\n", guestfs_int_program_name, r, guestfs_last_errno (g)); exit (EXIT_FAILURE); } print_rate ("virtio-serial upload rate:", rate); } if (virtio_serial_download) { /* For the download test, download a sparse file within the * appliance to /dev/null on the host. */ if (guestfs_touch (g, "/sparse") == -1) exit (EXIT_FAILURE); if (guestfs_truncate_size (g, "/sparse", TEST_SERIAL_MAX_SIZE) == -1) exit (EXIT_FAILURE); gettimeofday (&start, NULL); rate = -1; operation = "download"; alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME); guestfs_push_error_handler (g, NULL, NULL); r = guestfs_download (g, "/sparse", "/dev/null"); alarm (0); guestfs_pop_error_handler (g); if (r == -1 && guestfs_last_errno (g) != EINTR) { fprintf (stderr, "%s: expecting download command to return EINTR\n%s\n", guestfs_int_program_name, guestfs_last_error (g)); exit (EXIT_FAILURE); } if (rate == -1) goto rate_error; print_rate ("virtio-serial download rate:", rate); } if (guestfs_shutdown (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); /* Restore SIGALRM signal handler. */ sigaction (SIGALRM, &old_sa, NULL); }
static void * start_thread (void *vi) { guestfs_h *g; int r, thread_id = *(int *)vi; const char *error; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); *(int *)vi = -1; pthread_exit (vi); } if (guestfs_add_drive_opts (g, "/dev/null", GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) == -1) { *(int *)vi = -1; pthread_exit (vi); } /* Fake out qemu. */ if (guestfs_set_qemu (g, "/bin/true") == -1) { *(int *)vi = -1; pthread_exit (vi); } /* Wait for the other threads to finish starting up. */ r = pthread_barrier_wait (&barrier); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { fprintf (stderr, "pthread_barrier_wait: [thread %d]: %s\n", thread_id, strerror (r)); *(int *)vi = -1; pthread_exit (vi); } /* Launch the handle. Because of the faked out qemu, we expect this * will fail with "child process died unexpectedly". We are * interested in other failures. */ guestfs_push_error_handler (g, NULL, NULL); r = guestfs_launch (g); error = guestfs_last_error (g); if (r == 0) { /* This should NOT happen. */ fprintf (stderr, "rhbz790721: [thread %d]: " "strangeness in test: expected launch to fail, but it didn't!\n", thread_id); *(int *)vi = -1; pthread_exit (vi); } if (error == NULL) { /* This also should NOT happen. */ fprintf (stderr, "rhbz790721: [thread %d]: " "strangeness in test: no error message!\n", thread_id); *(int *)vi = -1; pthread_exit (vi); } /* If this happens, it indicates a bug/race in the appliance * building code which is what this regression test is designed to * spot. */ if (STRNEQ (error, "child process died unexpectedly")) { fprintf (stderr, "rhbz790721: [thread %d]: error: %s\n", thread_id, error); *(int *)vi = -1; pthread_exit (vi); } guestfs_pop_error_handler (g); /* Close the handle. */ guestfs_close (g); *(int *)vi = 0; pthread_exit (vi); }
int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:hlvVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "all", 0, 0, 0 }, { "blkdevs", 0, 0, 0 }, { "block-devices", 0, 0, 0 }, { "connect", 1, 0, 'c' }, { "csv", 0, 0, 0 }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "extra", 0, 0, 0 }, { "filesystems", 0, 0, 0 }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "human-readable", 0, 0, 'h' }, { "keys-from-stdin", 0, 0, 0 }, { "logical-volumes", 0, 0, 0 }, { "logvols", 0, 0, 0 }, { "long", 0, 0, 'l' }, { "long-options", 0, 0, 0 }, { "lvs", 0, 0, 0 }, { "no-title", 0, 0, 0 }, { "parts", 0, 0, 0 }, { "partitions", 0, 0, 0 }, { "physical-volumes", 0, 0, 0 }, { "physvols", 0, 0, 0 }, { "pvs", 0, 0, 0 }, { "uuid", 0, 0, 0 }, { "uuids", 0, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { "vgs", 0, 0, 0 }, { "volgroups", 0, 0, 0 }, { "volume-groups", 0, 0, 0 }, { 0, 0, 0, 0 } }; struct drv *drvs = NULL; struct drv *drv; const char *format = NULL; int c; int option_index; int no_title = 0; /* --no-title */ int long_mode = 0; /* --long|-l */ int uuid = 0; /* --uuid */ int title; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } 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, "long-options")) display_long_options (long_options); else 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 if (STREQ (long_options[option_index].name, "all")) { output = OUTPUT_ALL; } else if (STREQ (long_options[option_index].name, "blkdevs") || STREQ (long_options[option_index].name, "block-devices")) { output |= OUTPUT_BLOCKDEVS; } else if (STREQ (long_options[option_index].name, "csv")) { csv = 1; } else if (STREQ (long_options[option_index].name, "extra")) { output |= OUTPUT_FILESYSTEMS; output |= OUTPUT_FILESYSTEMS_EXTRA; } else if (STREQ (long_options[option_index].name, "filesystems")) { output |= OUTPUT_FILESYSTEMS; } else if (STREQ (long_options[option_index].name, "logical-volumes") || STREQ (long_options[option_index].name, "logvols") || STREQ (long_options[option_index].name, "lvs")) { output |= OUTPUT_LVS; } else if (STREQ (long_options[option_index].name, "no-title")) { no_title = 1; } else if (STREQ (long_options[option_index].name, "parts") || STREQ (long_options[option_index].name, "partitions")) { output |= OUTPUT_PARTITIONS; } else if (STREQ (long_options[option_index].name, "physical-volumes") || STREQ (long_options[option_index].name, "physvols") || STREQ (long_options[option_index].name, "pvs")) { output |= OUTPUT_PVS; } else if (STREQ (long_options[option_index].name, "uuid") || STREQ (long_options[option_index].name, "uuids")) { uuid = 1; } else if (STREQ (long_options[option_index].name, "vgs") || STREQ (long_options[option_index].name, "volgroups") || STREQ (long_options[option_index].name, "volume-groups")) { output |= OUTPUT_VGS; } 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 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'h': human = 1; break; case 'l': long_mode = 1; break; 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); } } /* 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 == 1); assert (inspector == 0); assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) usage (EXIT_FAILURE); /* -h and --csv doesn't make sense. Spreadsheets will corrupt these * fields. (RHBZ#600977). */ if (human && csv) { fprintf (stderr, _("%s: you cannot use -h and --csv options together.\n"), program_name); exit (EXIT_FAILURE); } /* Nothing selected for output, means --filesystems is implied. */ if (output == 0) output = OUTPUT_FILESYSTEMS; /* What columns will be displayed? */ columns = COLUMN_NAME; if (long_mode) { columns |= COLUMN_TYPE; columns |= COLUMN_SIZE; if ((output & OUTPUT_FILESYSTEMS)) { columns |= COLUMN_VFS_TYPE; columns |= COLUMN_VFS_LABEL; } columns |= COLUMN_PARENTS; if ((output & OUTPUT_PARTITIONS)) columns |= COLUMN_MBR; if (uuid) columns |= COLUMN_UUID; } /* Display title by default only in long mode. */ title = long_mode; if (no_title) title = 0; /* 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); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); if (title) do_output_title (); do_output (); do_output_end (); free_pvs (); guestfs_close (g); exit (EXIT_SUCCESS); }
/* Worker thread. */ static void * start_thread (void *thread_data_vp) { struct thread_data *thread_data = thread_data_vp; int quit = 0; int err; size_t i; guestfs_h *g; unsigned errors = 0; for (;;) { /* Take the next process. */ err = pthread_mutex_lock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_lock: %s", guestfs_int_program_name, strerror (err)); goto error; } i = n; if (i > 0) { printf ("%zu to go ... \r", n); fflush (stdout); n--; } else quit = 1; err = pthread_mutex_unlock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_unlock: %s", guestfs_int_program_name, strerror (err)); goto error; } if (quit) /* Work finished. */ break; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); errors++; if (!ignore_errors) goto error; } guestfs_set_trace (g, trace); guestfs_set_verbose (g, verbose); if (guestfs_add_drive_ro (g, "/dev/null") == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_launch (g) == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_shutdown (g) == -1) { errors++; if (!ignore_errors) goto error; } guestfs_close (g); } if (errors > 0) { fprintf (stderr, "%s: thread %d: %u errors were ignored\n", guestfs_int_program_name, thread_data->thread_num, errors); goto error; } thread_data->r = 0; return &thread_data->r; error: thread_data->r = -1; return &thread_data->r; }
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); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:hivVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "connect", 1, 0, 'c' }, { "csv", 0, 0, 0 }, { "domain", 1, 0, 'd' }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "human-readable", 0, 0, 'h' }, { "inodes", 0, 0, 'i' }, { "one-per-guest", 0, 0, 0 }, { "uuid", 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; 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, "format")) { if (!optarg || STREQ (optarg, "")) format = NULL; else format = optarg; } else if (STREQ (long_options[option_index].name, "csv")) { csv = 1; } else if (STREQ (long_options[option_index].name, "one-per-guest")) { one_per_guest = 1; } else if (STREQ (long_options[option_index].name, "uuid")) { uuid = 1; } 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 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'h': human = 1; break; case 'i': inodes = 1; break; 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-df which is how we detect this. */ if (drvs == NULL) { while (optind < argc) { 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 == 1); assert (inspector == 0); assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) usage (EXIT_FAILURE); /* -h and --csv doesn't make sense. Spreadsheets will corrupt these * fields. (RHBZ#600977). */ if (human && csv) { fprintf (stderr, _("%s: you cannot use -h and --csv options together.\n"), program_name); exit (EXIT_FAILURE); } /* If the user didn't specify any drives, then we ask libvirt for * the full list of guests and drives, which we add in batches. */ if (drvs == NULL) { #ifdef HAVE_LIBVIRT get_domains_from_libvirt (); #else fprintf (stderr, _("%s: compiled without support for libvirt.\n"), program_name); exit (EXIT_FAILURE); #endif } else { const char *name; /* Add domains/drives from the command line (for a single guest). */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); print_title (); /* Synthesize a display name. */ switch (drvs->type) { case drv_a: name = strrchr (drvs->a.filename, '/'); if (name == NULL) name = drvs->a.filename; else name++; /* skip '/' character */ break; case drv_d: name = drvs->d.guest; break; case drv_N: default: abort (); } /* XXX regression: in the Perl version we cached the UUID from the * libvirt domain handle so it was available to us here. In this * version the libvirt domain handle is hidden inside * guestfs_add_domain so the UUID is not available easily for * single '-d' command-line options. */ (void) df_on_handle (name, NULL, NULL, 0); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); } guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { /* Current time for --time-days, --time-relative output. */ time (&now); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:hlRvVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "checksum", 2, 0, 0 }, { "checksums", 2, 0, 0 }, { "csv", 0, 0, 0 }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "extra-stat", 0, 0, 0 }, { "extra-stats", 0, 0, 0 }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "human-readable", 0, 0, 'h' }, { "keys-from-stdin", 0, 0, 0 }, { "long", 0, 0, 'l' }, { "long-options", 0, 0, 0 }, { "recursive", 0, 0, 'R' }, { "time", 0, 0, 0 }, { "times", 0, 0, 0 }, { "time-days", 0, 0, 0 }, { "time-relative", 0, 0, 0 }, { "time-t", 0, 0, 0 }, { "uid", 0, 0, 0 }, { "uids", 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; #define MODE_LS_L 1 #define MODE_LS_R 2 #define MODE_LS_LR (MODE_LS_L|MODE_LS_R) int mode = 0; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } 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, "long-options")) display_long_options (long_options); else 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 if (STREQ (long_options[option_index].name, "checksum") || STREQ (long_options[option_index].name, "checksums")) { if (!optarg || STREQ (optarg, "")) checksum = "md5"; else checksum = optarg; } else if (STREQ (long_options[option_index].name, "csv")) { csv = 1; } else if (STREQ (long_options[option_index].name, "extra-stat") || STREQ (long_options[option_index].name, "extra-stats")) { enable_extra_stats = 1; } else if (STREQ (long_options[option_index].name, "time") || STREQ (long_options[option_index].name, "times")) { enable_times = 1; } else if (STREQ (long_options[option_index].name, "time-t")) { enable_times = 1; time_t_output = 1; } else if (STREQ (long_options[option_index].name, "time-relative")) { enable_times = 1; time_t_output = 1; time_relative = 1; } else if (STREQ (long_options[option_index].name, "time-days")) { enable_times = 1; time_t_output = 1; time_relative = 2; } else if (STREQ (long_options[option_index].name, "uid") || STREQ (long_options[option_index].name, "uids")) { enable_uids = 1; } 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 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'h': human = 1; break; case 'l': mode |= MODE_LS_L; break; case 'R': mode |= MODE_LS_R; break; 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-ls which is how we detect this. */ if (drvs == NULL) { /* argc - 1 because last parameter is the single directory name. */ while (optind < argc - 1) { if (strchr (argv[optind], '/') || access (argv[optind], F_OK) == 0) { /* simulate -a option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_a; drv->a.filename = strdup (argv[optind]); if (!drv->a.filename) { perror ("strdup"); exit (EXIT_FAILURE); } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ drv = calloc (1, 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 == 1); assert (inspector == 1); assert (live == 0); /* Many flags only apply to -lR mode. */ if (mode != MODE_LS_LR && (csv || human || enable_uids || enable_times || enable_extra_stats || checksum)) { fprintf (stderr, _("%s: used a flag which can only be combined with -lR mode\nFor more information, read the virt-ls(1) man page.\n"), program_name); exit (EXIT_FAILURE); } /* CSV && human is unsafe because spreadsheets fail to parse these * fields correctly. (RHBZ#600977). */ if (human && csv) { fprintf (stderr, _("%s: you cannot use -h and --csv options together.\n"), program_name); exit (EXIT_FAILURE); } /* User must specify at least one directory name 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, inspect and mount. Note that inspector is always true, * and there is no -m option. */ 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); unsigned errors = 0; while (optind < argc) { const char *dir = argv[optind]; switch (mode) { case 0: /* no -l or -R option */ if (do_ls (dir) == -1) errors++; break; case MODE_LS_L: /* virt-ls -l */ if (do_ls_l (dir) == -1) errors++; break; case MODE_LS_R: /* virt-ls -R */ if (do_ls_R (dir) == -1) errors++; break; case MODE_LS_LR: /* virt-ls -lR */ if (do_ls_lR (dir) == -1) errors++; break; default: abort (); /* can't happen */ } optind++; } guestfs_close (g); exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
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); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:qvVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "quiet", 0, 0, 'q' }, { "uuid", 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; int uuid = 0; /* This just needs to be larger than any alignment we care about. */ size_t worst_alignment = UINT_MAX; int exit_code; 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, "format")) { if (!optarg || STREQ (optarg, "")) format = NULL; else format = optarg; } else if (STREQ (long_options[option_index].name, "uuid")) { uuid = 1; } 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 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'q': quiet = 1; break; 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); } } /* 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 == 1); assert (inspector == 0); assert (live == 0); /* Must be no extra arguments on the command line. */ if (optind != argc) usage (EXIT_FAILURE); /* The user didn't specify any drives to scan. */ if (drvs == NULL) { #if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2) get_domains_from_libvirt (uuid, &worst_alignment); #else fprintf (stderr, _("%s: compiled without support for libvirt and/or libxml2.\n"), program_name); exit (EXIT_FAILURE); #endif } else { if (uuid) { fprintf (stderr, _("%s: --uuid option cannot be used with -a or -d\n"), program_name); exit (EXIT_FAILURE); } /* Add domains/drives from the command line (for a single guest). */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); /* Perform the scan. */ scan (&worst_alignment, NULL); guestfs_close (g); } /* Decide on an appropriate exit code. */ if (worst_alignment < 10) /* 2^10 = 4096 */ exit_code = 3; else if (worst_alignment < 16) /* 2^16 = 65536 */ exit_code = 2; else exit_code = 0; exit (exit_code); }