Пример #1
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  int r;

  g = guestfs_create ();
  if (g == NULL)
    error (EXIT_FAILURE, errno, "guestfs_create");

  /* If these fail, the default error handler will print an error
   * message to stderr, so we don't need to print anything.  This code
   * is very pedantic, but after all we are testing the details of the
   * C API.
   */

  if (guestfs_set_verbose (g, 1) == -1)
    exit (EXIT_FAILURE);
  r = guestfs_get_verbose (g);
  if (r == -1)
    exit (EXIT_FAILURE);
  if (!r)
    error (EXIT_FAILURE, 0, "set_verbose not true");
  if (guestfs_set_verbose (g, 0) == -1)
    exit (EXIT_FAILURE);
  r = guestfs_get_verbose (g);
  if (r == -1)
    exit (EXIT_FAILURE);
  if (r)
    error (EXIT_FAILURE, 0, "set_verbose not false");

  guestfs_close (g);

  exit (EXIT_SUCCESS);
}
Пример #2
0
/* Common function to set up event callbacks and record data in memory
 * for a particular pass (0 <= pass < NR_TEST_PASSES).
 */
static void
set_up_event_handlers (guestfs_h *g, size_t pass)
{
  struct pass_data *data;

  assert (/* 0 <= pass && */ pass < NR_TEST_PASSES);

  data = &pass_data[pass];
  data->pass = pass;
  data->nr_events = 0;
  data->events = NULL;
  get_time (&data->start_t);
  data->incomplete_log_message = -1;
  data->seen_launch = 0;

  guestfs_set_event_callback (g, close_callback,
                              GUESTFS_EVENT_CLOSE, 0, data);
  guestfs_set_event_callback (g, subprocess_quit_callback,
                              GUESTFS_EVENT_SUBPROCESS_QUIT, 0, data);
  guestfs_set_event_callback (g, launch_done_callback,
                              GUESTFS_EVENT_LAUNCH_DONE, 0, data);
  guestfs_set_event_callback (g, appliance_callback,
                              GUESTFS_EVENT_APPLIANCE, 0, data);
  guestfs_set_event_callback (g, library_callback,
                              GUESTFS_EVENT_LIBRARY, 0, data);
  guestfs_set_event_callback (g, trace_callback,
                              GUESTFS_EVENT_TRACE, 0, data);

  guestfs_set_verbose (g, 1);
  guestfs_set_trace (g, 1);
}
Пример #3
0
static size_t
add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r)
{
  size_t nr_disks_added;

  if (disk == NULL)
    return 0;

  nr_disks_added = add_disks_to_handle_reverse (disk->next, errors_r);

  struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 };

  optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
  optargs.readonly = 1;

  if (disk->format) {
    optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
    optargs.format = disk->format;
  }

  if (guestfs_add_drive_opts_argv (g, disk->filename, &optargs) == -1) {
    (*errors_r)++;
    disk->failed = 1;
    return nr_disks_added;
  }

  return nr_disks_added+1;
}

/* Close and reopen the libguestfs handle. */
static void
reset_guestfs_handle (void)
{
  /* Copy the settings from the old handle. */
  int verbose = guestfs_get_verbose (g);
  int trace = guestfs_get_trace (g);

  guestfs_close (g);

  g = guestfs_create ();
  if (g == NULL) {
    fprintf (stderr, _("guestfs_create: failed to create handle\n"));
    exit (EXIT_FAILURE);
  }

  guestfs_set_verbose (g, verbose);
  guestfs_set_trace (g, trace);
}
Пример #4
0
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);
}
Пример #5
0
/* 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;
}
Пример #6
0
static int
parse_environment (guestfs_h *g,
                   char *(*do_getenv) (const void *data, const char *),
                   const void *data)
{
  int memsize, b;
  char *str;

  /* Don't bother checking the return values of functions
   * that cannot return errors.
   */

  str = do_getenv (data, "LIBGUESTFS_TRACE");
  if (str) {
    b = guestfs_int_is_true (str);
    if (b == -1) {
      error (g, _("%s=%s: non-boolean value"), "LIBGUESTFS_TRACE", str);
      return -1;
    }
    guestfs_set_trace (g, b);
  }

  str = do_getenv (data, "LIBGUESTFS_DEBUG");
  if (str) {
    b = guestfs_int_is_true (str);
    if (b == -1) {
      error (g, _("%s=%s: non-boolean value"), "LIBGUESTFS_TRACE", str);
      return -1;
    }
    guestfs_set_verbose (g, b);
  }

  str = do_getenv (data, "LIBGUESTFS_TMPDIR");
  if (str && STRNEQ (str, "")) {
    if (guestfs_set_tmpdir (g, str) == -1)
      return -1;
  }

  str = do_getenv (data, "LIBGUESTFS_CACHEDIR");
  if (str && STRNEQ (str, "")) {
    if (guestfs_set_cachedir (g, str) == -1)
      return -1;
  }

  str = do_getenv (data, "TMPDIR");
  if (guestfs_int_set_env_tmpdir (g, str) == -1)
    return -1;

  str = do_getenv (data, "LIBGUESTFS_PATH");
  if (str && STRNEQ (str, ""))
    guestfs_set_path (g, str);

  str = do_getenv (data, "LIBGUESTFS_HV");
  if (str && STRNEQ (str, ""))
    guestfs_set_hv (g, str);
  else {
    str = do_getenv (data, "LIBGUESTFS_QEMU");
    if (str && STRNEQ (str, ""))
      guestfs_set_hv (g, str);
  }

  str = do_getenv (data, "LIBGUESTFS_APPEND");
  if (str)
    guestfs_set_append (g, str);

  str = do_getenv (data, "LIBGUESTFS_MEMSIZE");
  if (str && STRNEQ (str, "")) {
    if (sscanf (str, "%d", &memsize) != 1) {
      error (g, _("non-numeric value for LIBGUESTFS_MEMSIZE"));
      return -1;
    }
    if (guestfs_set_memsize (g, memsize) == -1) {
      /* set_memsize produces an error message already. */
      return -1;
    }
  }

  str = do_getenv (data, "LIBGUESTFS_BACKEND");
  if (str && STRNEQ (str, "")) {
    if (guestfs_set_backend (g, str) == -1)
      return -1;
  }
  else {
    str = do_getenv (data, "LIBGUESTFS_ATTACH_METHOD");
    if (str && STRNEQ (str, "")) {
      if (guestfs_set_backend (g, str) == -1)
        return -1;
    }
  }

  str = do_getenv (data, "LIBGUESTFS_BACKEND_SETTINGS");
  if (str) {
    CLEANUP_FREE_STRING_LIST char **settings = guestfs_int_split_string (':', str);

    if (settings == NULL) {
      perrorf (g, "split_string: malloc");
      return -1;
    }

    if (guestfs_set_backend_settings (g, settings) == -1)
      return -1;
  }

  return 0;
}
Пример #7
0
/* 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;
}
Пример #8
0
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:A:c:d:D:hvVx";
    static const struct option long_options[] = {
        { "add", 1, 0, 'a' },
        { "all", 0, 0, 0 },
        { "atime", 0, 0, 0 },
        { "checksum", 2, 0, 0 },
        { "checksums", 2, 0, 0 },
        { "csv", 0, 0, 0 },
        { "connect", 1, 0, 'c' },
        { "dir-link", 0, 0, 0 },
        { "dir-links", 0, 0, 0 },
        { "dir-nlink", 0, 0, 0 },
        { "dir-nlinks", 0, 0, 0 },
        { "dir-time", 0, 0, 0 },
        { "dir-times", 0, 0, 0 },
        { "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 },
        { "short-options", 0, 0, 0 },
        { "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' },
        { "xattr", 0, 0, 0 },
        { "xattrs", 0, 0, 0 },
        { 0, 0, 0, 0 }
    };
    struct drv *drvs = NULL;      /* First guest. */
    struct drv *drvs2 = NULL;     /* Second guest. */
    const char *format = NULL;
    bool format_consumed = true;
    int c;
    int option_index;
    struct tree *tree1, *tree2;

    g = guestfs_create ();
    if (g == NULL) {
        fprintf (stderr, _("guestfs_create: failed to create handle\n"));
        exit (EXIT_FAILURE);
    }

    g2 = guestfs_create ();
    if (g2 == 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, "all")) {
                enable_extra_stats = enable_times = enable_uids = enable_xattrs = 1;
            } else if (STREQ (long_options[option_index].name, "atime")) {
                atime = 1;
            } else if (STREQ (long_options[option_index].name, "csv")) {
                csv = 1;
            } 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, "dir-link") ||
                       STREQ (long_options[option_index].name, "dir-links") ||
                       STREQ (long_options[option_index].name, "dir-nlink") ||
                       STREQ (long_options[option_index].name, "dir-nlinks")) {
                dir_links = 1;
            } else if (STREQ (long_options[option_index].name, "dir-time") ||
                       STREQ (long_options[option_index].name, "dir-times")) {
                dir_times = 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 if (STREQ (long_options[option_index].name, "xattr") ||
                       STREQ (long_options[option_index].name, "xattrs")) {
                enable_xattrs = 1;
            } 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 'A':
            OPTION_A;
            break;

        case 'c':
            OPTION_c;
            break;

        case 'd':
            OPTION_d;
            break;

        case 'D':
            OPTION_D;
            break;

        case 'h':
            human = 1;
            break;

        case 'v':
            /* OPTION_v; */
            verbose++;
            guestfs_set_verbose (g, verbose);
            guestfs_set_verbose (g2, verbose);
            break;

        case 'V':
            OPTION_V;
            break;

        case 'x':
            /* OPTION_x; */
            guestfs_set_trace (g, 1);
            guestfs_set_trace (g2, 1);
            break;

        case HELP_OPTION:
            usage (EXIT_SUCCESS);

        default:
            usage (EXIT_FAILURE);
        }
    }

    if (drvs == NULL || drvs2 == NULL) {
        fprintf (stderr,
                 _("%s: you must specify some -a|-A|-d|-D options, see %s(1)\n"),
                 guestfs_int_program_name, guestfs_int_program_name);
        usage (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"),
                 guestfs_int_program_name);
        exit (EXIT_FAILURE);
    }

    if (optind != argc) {
        fprintf (stderr, _("%s: extra arguments on the command line\n"),
                 guestfs_int_program_name);
        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);

    CHECK_OPTION_format_consumed;

    unsigned errors = 0;

    /* Mount up first guest. */
    add_drives (drvs, 'a');

    if (guestfs_launch (g) == -1)
        exit (EXIT_FAILURE);

    inspect_mount ();

    if ((tree1 = visit_guest (g)) == NULL)
        errors++;

    /* Mount up second guest. */
    add_drives_handle (g2, drvs2, 'a');

    if (guestfs_launch (g2) == -1)
        exit (EXIT_FAILURE);

    inspect_mount_handle (g2);

    if ((tree2 = visit_guest (g2)) == NULL)
        errors++;

    if (errors == 0) {
        if (diff_guests (tree1, tree2) == -1)
            errors++;
    }

    free_tree (tree1);
    free_tree (tree2);

    free_drives (drvs);
    free_drives (drvs2);

    guestfs_close (g);
    guestfs_close (g2);

    exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
Пример #9
0
/* Worker thread. */
static void *
worker_thread (void *thread_data_vp)
{
  struct thread_data *thread_data = thread_data_vp;

  thread_data->r = 0;

  if (thread_data->verbose)
    fprintf (stderr, "parallel: thread %zu starting\n",
             thread_data->thread_num);

  while (1) {
    size_t i;               /* The current domain we're working on. */
    FILE *fp;
    CLEANUP_FREE char *output = NULL;
    size_t output_len = 0;
    guestfs_h *g;
    int err;
    char id[64];

    /* Take the next domain from the list. */
    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu waiting to get work\n",
               thread_data->thread_num);

    err = pthread_mutex_lock (&take_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_lock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
    i = next_domain_to_take++;
    err = pthread_mutex_unlock (&take_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_unlock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }

    if (i >= nr_domains)        /* Work finished. */
      break;

    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu taking domain %zu\n",
               thread_data->thread_num, i);

    fp = open_memstream (&output, &output_len);
    if (fp == NULL) {
      perror ("open_memstream");
      thread_data->r = -1;
      return &thread_data->r;
    }

    /* Create a guestfs handle. */
    g = guestfs_create ();
    if (g == NULL) {
      perror ("guestfs_create");
      thread_data->r = -1;
      return &thread_data->r;
    }

    /* Set the handle identifier so we can tell threads apart. */
    snprintf (id, sizeof id, "thread_%zu_domain_%zu",
              thread_data->thread_num, i);
    guestfs_set_identifier (g, id);

    /* Copy some settings from the options guestfs handle. */
    guestfs_set_trace (g, thread_data->trace);
    guestfs_set_verbose (g, thread_data->verbose);

    /* Do work. */
    if (thread_data->work (g, i, fp) == -1) {
      thread_data->r = -1;

      if (thread_data->verbose)
        fprintf (stderr,
                 "parallel: thread %zu work function returned an error\n",
                 thread_data->thread_num);
    }

    fclose (fp);
    guestfs_close (g);

    /* Retire this domain.  We have to retire domains in order, which
     * may mean waiting for another thread to finish here.
     */
    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu waiting to retire domain %zu\n",
               thread_data->thread_num, i);

    err = pthread_mutex_lock (&retire_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_lock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
    while (next_domain_to_retire != i) {
      err = pthread_cond_wait (&retire_cond, &retire_mutex);
      if (err != 0) {
        thread_failure ("pthread_cond_wait", err);
        thread_data->r = -1;
        ignore_value (pthread_mutex_unlock (&retire_mutex));
        return &thread_data->r;
      }
    }

    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu retiring domain %zu\n",
               thread_data->thread_num, i);

    /* Retire domain. */
    printf ("%s", output);

    /* Update next_domain_to_retire and tell other threads. */
    next_domain_to_retire = i+1;
    pthread_cond_broadcast (&retire_cond);
    err = pthread_mutex_unlock (&retire_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_unlock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
  }

  if (thread_data->verbose)
    fprintf (stderr, "parallel: thread %zu exiting (r = %d)\n",
             thread_data->thread_num, thread_data->r);

  return &thread_data->r;
}
Пример #10
0
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' },
    { "filesystem", 1, 0, 0 },
    { "format", 2, 0, 0 },
    { "help", 0, 0, HELP_OPTION },
    { "lvm", 2, 0, 0 },
    { "partition", 2, 0, 0 },
    { "verbose", 0, 0, 'v' },
    { "version", 0, 0, 'V' },
    { "wipe", 0, 0, 0 },
    { 0, 0, 0, 0 }
  };
  struct drv *drvs = NULL;
  struct drv *drv;
  const char *format = NULL;
  int c;
  int option_index;
  int retry, retries;

  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, "filesystem")) {
        if (STREQ (optarg, "none"))
          filesystem = NULL;
        else if (optarg[0] == '-') { /* eg: --filesystem --lvm */
          fprintf (stderr, _("%s: no filesystem was specified\n"),
                   program_name);
          exit (EXIT_FAILURE);
        } else
          filesystem = optarg;
      } else if (STREQ (long_options[option_index].name, "lvm")) {
        if (vg || lv) {
          fprintf (stderr,
                   _("%s: --lvm option cannot be given multiple times\n"),
                   program_name);
          exit (EXIT_FAILURE);
        }
        if (optarg == NULL) {
          vg = strdup ("VG");
          lv = strdup ("LV");
          if (!vg || !lv) { perror ("strdup"); exit (EXIT_FAILURE); }
        }
        else if (STREQ (optarg, "none"))
          vg = lv = NULL;
        else
          parse_vg_lv (optarg);
      } else if (STREQ (long_options[option_index].name, "partition")) {
        if (optarg == NULL)
          partition = "DEFAULT";
        else if (STREQ (optarg, "none"))
          partition = NULL;
        else
          partition = optarg;
      } else if (STREQ (long_options[option_index].name, "wipe")) {
        wipe = 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 '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 == 0);
  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 format. */
  if (drvs == NULL)
    usage (EXIT_FAILURE);

  /* Because the libguestfs kernel can get stuck rereading the
   * partition table after things have been erased, we sometimes need
   * to completely restart the guest.  Hence this complex retry logic.
   */
  for (retries = 0; retries <= 1; ++retries) {
    /* Add domains/drives from the command line (for a single guest). */
    add_drives (drvs, 'a');

    if (guestfs_launch (g) == -1)
      exit (EXIT_FAILURE);

    /* Test if the wipefs API is available. */
    have_wipefs = feature_available (g, "wipefs");

    /* Perform the format. */
    retry = do_format ();
    if (!retry)
      break;

    if (retries == 0) {
      /* We're going to silently retry, after reopening the connection. */
      guestfs_h *g2;

      g2 = guestfs_create ();
      guestfs_set_verbose (g2, guestfs_get_verbose (g));
      guestfs_set_trace (g2, guestfs_get_trace (g));

      if (guestfs_shutdown (g) == -1)
        exit (EXIT_FAILURE);
      guestfs_close (g);
      g = g2;
    }
    else {
      /* Failed. */
      fprintf (stderr,
               _("%s: failed to rescan the disks after two attempts.  This\n"
                 "may mean there is some sort of partition table or disk\n"
                 "data which we are unable to remove.  If you think this\n"
                 "is a bug, please file a bug at http://libguestfs.org/\n"),
               program_name);
      exit (EXIT_FAILURE);
    }
  }

  /* Free up data structures. */
  free_drives (drvs);

  if (guestfs_shutdown (g) == -1)
    exit (EXIT_FAILURE);
  guestfs_close (g);

  exit (EXIT_SUCCESS);
}
Пример #11
0
int
run_reopen (const char *cmd, size_t argc, char *argv[])
{
  guestfs_h *g2;
  int r;
  const char *p;
  guestfs_error_handler_cb cb;
  void *cb_data;

  if (argc > 0) {
    fprintf (stderr, _("'reopen' command takes no parameters\n"));
    return -1;
  }

  if (guestfs_shutdown (g) == -1)
    return -1;

  /* Open the new handle first, so we can copy the settings from the
   * old one to the new one, and also so if it fails we still have an
   * open handle.
   */
  g2 = guestfs_create ();
  if (g2 == NULL) {
    fprintf (stderr, _("reopen: guestfs_create: failed to create handle\n"));
    return -1;
  }

  /* Now copy some of the settings from the old handle.  The settings
   * we copy are those which are set by guestfish itself.
   */
  cb = guestfs_get_error_handler (g, &cb_data);
  guestfs_set_error_handler (g2, cb, cb_data);

  r = guestfs_get_verbose (g);
  if (r >= 0)
    guestfs_set_verbose (g2, r);

  r = guestfs_get_trace (g);
  if (r >= 0)
    guestfs_set_trace (g2, r);

  r = guestfs_get_autosync (g);
  if (r >= 0)
    guestfs_set_autosync (g2, r);

  p = guestfs_get_path (g);
  if (p)
    guestfs_set_path (g2, p);

  r = guestfs_get_pgroup (g);
  if (r >= 0)
    guestfs_set_pgroup (g2, r);

  if (progress_bars)
    guestfs_set_event_callback (g2, progress_callback,
                                GUESTFS_EVENT_PROGRESS, 0, NULL);

  /* Close the original handle. */
  guestfs_close (g);
  g = g2;

  /* We don't bother copying event handlers over to the new handle,
   * but we have to reset the list because they were registered
   * against the old handle.
   */
  free_event_handlers ();
  init_event_handlers ();

  return 0;
}