/* 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 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[]) { 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); }
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); }