Ejemplo n.º 1
0
value
guestfs_int_mllib_parse_uri (value argv /* arg value, not an array! */)
{
  CAMLparam1 (argv);
  CAMLlocal4 (rv, sv, ssv, ov);
  struct uri uri;
  int r;

  r = parse_uri (String_val (argv), &uri);
  if (r == -1)
    caml_invalid_argument ("URI.parse_uri");

  /* Convert the struct into an OCaml tuple. */
  rv = caml_alloc_tuple (5);

  /* path : string */
  sv = caml_copy_string (uri.path);
  free (uri.path);
  Store_field (rv, 0, sv);

  /* protocol : string */
  sv = caml_copy_string (uri.protocol);
  free (uri.protocol);
  Store_field (rv, 1, sv);

  /* server : string array option */
  if (uri.server) {
    ssv = caml_copy_string_array ((const char **) uri.server);
    guestfs_int_free_string_list (uri.server);
    ov = caml_alloc (1, 0);
    Store_field (ov, 0, ssv);
  }
  else
    ov = Val_int (0);
  Store_field (rv, 2, ov);

  /* username : string option */
  if (uri.username) {
    sv = caml_copy_string (uri.username);
    free (uri.username);
    ov = caml_alloc (1, 0);
    Store_field (ov, 0, sv);
  }
  else
    ov = Val_int (0);
  Store_field (rv, 3, ov);

  /* password : string option */
  if (uri.password) {
    sv = caml_copy_string (uri.password);
    free (uri.password);
    ov = caml_alloc (1, 0);
    Store_field (ov, 0, sv);
  }
  else
    ov = Val_int (0);
  Store_field (rv, 4, ov);

  CAMLreturn (rv);
}
Ejemplo n.º 2
0
void
free_config (struct config *c)
{
  free (c->server);
  free (c->username);
  free (c->password);
  free (c->identity_url);
  free (c->identity_file);
  free (c->guestname);
  guestfs_int_free_string_list (c->disks);
  guestfs_int_free_string_list (c->removable);
  guestfs_int_free_string_list (c->interfaces);
  guestfs_int_free_string_list (c->network_map);
  free (c->output);
  free (c->output_connection);
  free (c->output_format);
  free (c->output_storage);
  free (c);
}
Ejemplo n.º 3
0
/**
 * Test C<guestfs_int_split_string>.
 */
static void
test_split (void)
{
  char **ret;

  ret = guestfs_int_split_string (':', "");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 0);
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', "a");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 1);
  assert (STREQ (ret[0], "a"));
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', ":");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 2);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], ""));
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', "::");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 3);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], ""));
  assert (STREQ (ret[2], ""));
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', ":a");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 2);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], "a"));
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', "a:");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 2);
  assert (STREQ (ret[0], "a"));
  assert (STREQ (ret[1], ""));
  guestfs_int_free_string_list (ret);

  ret = guestfs_int_split_string (':', "a:b:c");
  assert (ret);
  assert (guestfs_int_count_strings (ret) == 3);
  assert (STREQ (ret[0], "a"));
  assert (STREQ (ret[1], "b"));
  assert (STREQ (ret[2], "c"));
  guestfs_int_free_string_list (ret);
}
Ejemplo n.º 4
0
int
guestfs_impl_set_backend_settings (guestfs_h *g, char *const *settings)
{
  char **copy;

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

  guestfs_int_free_string_list (g->backend_settings);
  g->backend_settings = copy;

  return 0;
}
Ejemplo n.º 5
0
/* Get the first matching line (using egrep [-i]) of a small file,
 * without any trailing newline character.
 *
 * Returns: 1 = returned a line (in *ret)
 *          0 = no match
 *          -1 = error
 */
int
guestfs_int_first_egrep_of_file (guestfs_h *g, const char *filename,
				 const char *eregex, int iflag, char **ret)
{
  char **lines;
  int64_t size;
  size_t i;
  struct guestfs_grep_opts_argv optargs;

  /* Don't trust guestfs_grep not to break with very large files.
   * Check the file size is something reasonable first.
   */
  size = guestfs_filesize (g, filename);
  if (size == -1)
    /* guestfs_filesize failed and has already set error in handle */
    return -1;
  if (size > MAX_SMALL_FILE_SIZE) {
    error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
           filename, size);
    return -1;
  }

  optargs.bitmask = GUESTFS_GREP_OPTS_EXTENDED_BITMASK;
  optargs.extended = 1;
  if (iflag) {
    optargs.bitmask |= GUESTFS_GREP_OPTS_INSENSITIVE_BITMASK;
    optargs.insensitive = 1;
  }
  lines = guestfs_grep_opts_argv (g, eregex, filename, &optargs);
  if (lines == NULL)
    return -1;
  if (lines[0] == NULL) {
    guestfs_int_free_string_list (lines);
    return 0;
  }

  *ret = lines[0];              /* caller frees */

  /* free up any other matches and the array itself */
  for (i = 1; lines[i] != NULL; ++i)
    free (lines[i]);
  free (lines);

  return 1;
}
Ejemplo n.º 6
0
/* Get the first line of a small file, without any trailing newline
 * character.
 *
 * NOTE: If the file is completely empty or begins with a '\n'
 * character, this returns an empty string (not NULL).  The caller
 * will usually need to check for this case.
 */
char *
guestfs_int_first_line_of_file (guestfs_h *g, const char *filename)
{
  char **lines = NULL; /* sic: not CLEANUP_FREE_STRING_LIST */
  int64_t size;
  char *ret;

  /* Don't trust guestfs_head_n not to break with very large files.
   * Check the file size is something reasonable first.
   */
  size = guestfs_filesize (g, filename);
  if (size == -1)
    /* guestfs_filesize failed and has already set error in handle */
    return NULL;
  if (size > MAX_SMALL_FILE_SIZE) {
    error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
           filename, size);
    return NULL;
  }

  lines = guestfs_head_n (g, 1, filename);
  if (lines == NULL)
    return NULL;
  if (lines[0] == NULL) {
    guestfs_int_free_string_list (lines);
    /* Empty file: Return an empty string as explained above. */
    return safe_strdup (g, "");
  }
  /* lines[1] should be NULL because of '1' argument above ... */

  ret = lines[0];               /* caller frees */

  free (lines);

  return ret;
}
Ejemplo n.º 7
0
guestfs_h *
guestfs_create_flags (unsigned flags, ...)
{
  guestfs_h *g;

  g = calloc (1, sizeof (*g));
  if (!g) return NULL;

  g->state = CONFIG;

  g->conn = NULL;

  guestfs_int_init_error_handler (g);
  g->abort_cb = abort;

  g->recovery_proc = 1;
  g->autosync = 1;

  g->memsize = DEFAULT_MEMSIZE;

  /* Start with large serial numbers so they are easy to spot
   * inside the protocol.
   */
  g->msg_next_serial = 0x00123400;

  /* Default is uniprocessor appliance. */
  g->smp = 1;

  g->path = strdup (GUESTFS_DEFAULT_PATH);
  if (!g->path) goto error;

#ifdef QEMU
  g->hv = strdup (QEMU);
#else
  /* configure --without-qemu, so set QEMU to something which will
   * definitely fail.  The user is expected to override the hypervisor
   * by setting an environment variable or calling set_hv.
   */
  g->hv = strdup ("false");
#endif
  if (!g->hv) goto error;

  /* Get program name. */
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1
  if (STRPREFIX (program_invocation_short_name, "lt-"))
    /* Remove libtool (lt-*) prefix from short name. */
    g->program = strdup (program_invocation_short_name + 3);
  else
    g->program = strdup (program_invocation_short_name);
#else
  g->program = strdup ("");
#endif
  if (!g->program) goto error;

  g->identifier = strdup ("");
  if (!g->identifier) goto error;

  if (guestfs_int_set_backend (g, DEFAULT_BACKEND) == -1) {
    warning (g, _("libguestfs was built with an invalid default backend, using 'direct' instead"));
    if (guestfs_int_set_backend (g, "direct") == -1) {
      warning (g, _("'direct' backend does not work"));
      goto error;
    }
  }

  if (!(flags & GUESTFS_CREATE_NO_ENVIRONMENT))
    ignore_value (guestfs_parse_environment (g));

  if (!(flags & GUESTFS_CREATE_NO_CLOSE_ON_EXIT)) {
    g->close_on_exit = true;

    /* Link the handles onto a global list. */
    gl_lock_lock (handles_lock);
    g->next = handles;
    handles = g;
    if (!atexit_handler_set) {
      atexit (close_handles);
      atexit_handler_set = 1;
    }
    gl_lock_unlock (handles_lock);
  }

  debug (g, "create: flags = %u, handle = %p, program = %s",
         flags, g, g->program);

  return g;

 error:
  guestfs_int_free_string_list (g->backend_settings);
  free (g->backend);
  free (g->identifier);
  free (g->program);
  free (g->path);
  free (g->hv);
  free (g->append);
  free (g);
  return NULL;
}
Ejemplo n.º 8
0
void
guestfs_close (guestfs_h *g)
{
  struct hv_param *hp, *hp_next;
  guestfs_h **gg;

  if (g->state == NO_HANDLE) {
    /* Not safe to call ANY callbacks here, so ... */
    fprintf (stderr, _("guestfs_close: called twice on the same handle\n"));
    return;
  }

  /* Remove the handle from the handles list. */
  if (g->close_on_exit) {
    gl_lock_lock (handles_lock);
    for (gg = &handles; *gg != g; gg = &(*gg)->next)
      ;
    *gg = g->next;
    gl_lock_unlock (handles_lock);
  }

  if (g->trace) {
    const char trace_msg[] = "close";

    guestfs_int_call_callbacks_message (g, GUESTFS_EVENT_TRACE,
					trace_msg, strlen (trace_msg));
  }

  debug (g, "closing guestfs handle %p (state %d)", g, (int) g->state);

  if (g->state != CONFIG)
    shutdown_backend (g, 0);

  /* Run user close callbacks. */
  guestfs_int_call_callbacks_void (g, GUESTFS_EVENT_CLOSE);

  /* Test output file used by bindtests. */
  if (g->test_fp != NULL)
    fclose (g->test_fp);

  /* Remove temporary directory. */
  guestfs_int_remove_tmpdir (g);

  /* Mark the handle as dead and then free up all memory. */
  g->state = NO_HANDLE;

  free (g->events);
  g->nr_events = 0;
  g->events = NULL;

#if HAVE_FUSE
  guestfs_int_free_fuse (g);
#endif

  guestfs_int_free_inspect_info (g);
  guestfs_int_free_drives (g);

  for (hp = g->hv_params; hp; hp = hp_next) {
    free (hp->hv_param);
    free (hp->hv_value);
    hp_next = hp->next;
    free (hp);
  }

  while (g->error_cb_stack)
    guestfs_pop_error_handler (g);

  if (g->pda)
    hash_free (g->pda);
  free (g->tmpdir);
  free (g->env_tmpdir);
  free (g->int_tmpdir);
  free (g->int_cachedir);
  free (g->last_error);
  free (g->identifier);
  free (g->program);
  free (g->path);
  free (g->hv);
  free (g->backend);
  free (g->backend_data);
  guestfs_int_free_string_list (g->backend_settings);
  free (g->append);
  free (g);
}
Ejemplo n.º 9
0
static int
parse (const char *arg, char **path_ret, char **protocol_ret,
       char ***server_ret, char **username_ret, char **password_ret)
{
  CLEANUP_XMLFREEURI xmlURIPtr uri = NULL;
  CLEANUP_FREE char *socket = NULL;
  char *path;

  uri = xmlParseURI (arg);
  if (!uri) {
    fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"),
             getprogname (), arg);
    return -1;
  }

  /* Note we don't do much checking of the parsed URI, since the
   * underlying function 'guestfs_add_drive_opts' will check for us.
   * So just the basics here.
   */
  if (uri->scheme == NULL || STREQ (uri->scheme, "")) {
    /* Probably can never happen. */
    fprintf (stderr, _("%s: %s: scheme of URI is NULL or empty\n"),
             getprogname (), arg);
    return -1;
  }

  socket = query_get (uri, "socket");

  if (uri->server && STRNEQ (uri->server, "") && socket) {
    fprintf (stderr, _("%s: %s: cannot both a server name and a socket query parameter\n"),
             getprogname (), arg);
    return -1;
  }

  /* Is this needed? XXX
  if (socket && socket[0] != '/') {
    fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute path\n"),
             getprogname (), arg);
    return -1;
  }
  */

  *protocol_ret = strdup (uri->scheme);
  if (*protocol_ret == NULL) {
    perror ("strdup: protocol");
    return -1;
  }

  if (make_server (uri, socket, server_ret) == -1) {
    free (*protocol_ret);
    return -1;
  }

  *password_ret = NULL;
  *username_ret = NULL;
  if (uri->user && STRNEQ (uri->user, "")) {
    char *p = strchr (uri->user, ':');
    if (p != NULL) {
      if (STRNEQ (p+1, "")) {
        *password_ret = strdup (p+1);
        if (*password_ret == NULL) {
          perror ("strdup: password");
          free (*protocol_ret);
          guestfs_int_free_string_list (*server_ret);
          return -1;
        }
      }
      *p = '\0';
    }
    *username_ret = strdup (uri->user);
    if (*username_ret == NULL) {
      perror ("strdup: username");
      free (*password_ret);
      free (*protocol_ret);
      guestfs_int_free_string_list (*server_ret);
      return -1;
    }
  }

  /* We may have to adjust the path depending on the protocol.  For
   * example ceph/rbd URIs look like rbd:///pool/disk, but the
   * exportname expected will be "pool/disk".  Here, uri->path will be
   * "/pool/disk" so we have to knock off the leading '/' character.
   */
  path = uri->path;
  if (path && path[0] == '/' &&
      (STREQ (uri->scheme, "gluster") ||
       STREQ (uri->scheme, "iscsi") ||
       STREQ (uri->scheme, "rbd") ||
       STREQ (uri->scheme, "sheepdog")))
    path++;

  *path_ret = strdup (path ? path : "");
  if (*path_ret == NULL) {
    perror ("strdup: path");
    free (*protocol_ret);
    guestfs_int_free_string_list (*server_ret);
    free (*username_ret);
    free (*password_ret);
    return -1;
  }

  return 0;
}
Ejemplo n.º 10
0
int
main (int argc, char *argv[])
{
  gboolean gui_possible;
  int c;
  int option_index;
  char **cmdline = NULL;
  int cmdline_source = 0;
  struct config *config = new_config ();

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEBASEDIR);
  textdomain (PACKAGE);

#if ! GLIB_CHECK_VERSION(2,32,0)
  /* In glib2 < 2.32 you had to call g_thread_init().  In later glib2
   * that is not required and should not be called.
   */
  if (glib_check_version (2, 32, 0) != NULL) /* This checks < 2.32 */
    g_thread_init (NULL);
#endif
  gdk_threads_init ();
  gdk_threads_enter ();
  gui_possible = gtk_init_check (&argc, &argv);

  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, "cmdline")) {
        cmdline = parse_cmdline_string (optarg);
        cmdline_source = CMDLINE_SOURCE_COMMAND_LINE;
      }
      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 'v':
      config->verbose = 1;
      break;

    case 'V':
      printf ("%s %s%s\n",
              guestfs_int_program_name,
              PACKAGE_VERSION, PACKAGE_VERSION_EXTRA);
      exit (EXIT_SUCCESS);

    case HELP_OPTION:
      usage (EXIT_SUCCESS);

    default:
      usage (EXIT_FAILURE);
    }
  }

  if (optind != argc) {
    fprintf (stderr, _("%s: unused arguments on the command line\n"),
             guestfs_int_program_name);
    usage (EXIT_FAILURE);
  }

  set_config_defaults (config);

  /* If /proc/cmdline exists and contains "p2v.server=" then we enable
   * non-interactive configuration.
   * If /proc/cmdline contains p2v.debug then we enable verbose mode
   * even for interactive configuration.
   */
  if (cmdline == NULL) {
    cmdline = parse_proc_cmdline ();
    if (cmdline == NULL)
      goto gui;
    cmdline_source = CMDLINE_SOURCE_PROC_CMDLINE;
  }

  if (get_cmdline_key (cmdline, "p2v.debug") != NULL)
    config->verbose = 1;

  if (get_cmdline_key (cmdline, "p2v.server") != NULL)
    kernel_configuration (config, cmdline, cmdline_source);
  else {
  gui:
    if (!gui_possible) {
      fprintf (stderr,
               _("%s: gtk_init_check returned false, indicating that\n"
                 "a GUI is not possible on this host.  Check X11, $DISPLAY etc.\n"),
               guestfs_int_program_name);
      exit (EXIT_FAILURE);
    }
    gui_application (config);
  }

  guestfs_int_free_string_list (cmdline);

  exit (EXIT_SUCCESS);
}
Ejemplo n.º 11
0
void
kernel_configuration (struct config *config, char **cmdline, int cmdline_source)
{
  const char *p;

  p = get_cmdline_key (cmdline, "p2v.pre");
  if (p)
    run_command (config->verbose, "p2v.pre", p);

  p = get_cmdline_key (cmdline, "p2v.server");
  assert (p); /* checked by caller */
  free (config->server);
  config->server = strdup (p);

  p = get_cmdline_key (cmdline, "p2v.port");
  if (p) {
    if (sscanf (p, "%d", &config->port) != 1) {
      fprintf (stderr, "%s: cannot parse p2v.port from kernel command line",
               guestfs_int_program_name);
      exit (EXIT_FAILURE);
    }
  }

  p = get_cmdline_key (cmdline, "p2v.username");
  if (p) {
    free (config->username);
    config->username = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.password");
  if (p) {
    free (config->password);
    config->password = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.identity");
  if (p) {
    free (config->identity_url);
    config->identity_url = strdup (p);
    config->identity_file_needs_update = 1;
  }

  p = get_cmdline_key (cmdline, "p2v.sudo");
  if (p)
    config->sudo = 1;

  /* We should now be able to connect and interrogate virt-v2v
   * on the conversion server.
   */
  p = get_cmdline_key (cmdline, "p2v.skip_test_connection");
  if (!p) {
    wait_network_online (config);
    if (test_connection (config) == -1) {
      const char *err = get_ssh_error ();

      fprintf (stderr, "%s: error opening control connection to %s:%d: %s\n",
               guestfs_int_program_name, config->server, config->port, err);
      exit (EXIT_FAILURE);
    }
  }

  p = get_cmdline_key (cmdline, "p2v.name");
  if (p) {
    free (config->guestname);
    config->guestname = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.vcpus");
  if (p) {
    if (sscanf (p, "%d", &config->vcpus) != 1) {
      fprintf (stderr, "%s: cannot parse p2v.vcpus from kernel command line\n",
               guestfs_int_program_name);
      exit (EXIT_FAILURE);
    }
  }

  p = get_cmdline_key (cmdline, "p2v.memory");
  if (p) {
    char mem_code;

    if (sscanf (p, "%" SCNu64 "%c", &config->memory, &mem_code) != 2) {
      fprintf (stderr, "%s: cannot parse p2v.memory from kernel command line\n",
               guestfs_int_program_name);
      exit (EXIT_FAILURE);
    }
    config->memory *= 1024;
    if (mem_code == 'M' || mem_code == 'm'
        || mem_code == 'G' || mem_code == 'g')
      config->memory *= 1024;
    if (mem_code == 'G' || mem_code == 'g')
      config->memory *= 1024;
    if (mem_code != 'M' && mem_code != 'm'
        && mem_code != 'G' && mem_code != 'g') {
      fprintf (stderr, "%s: p2v.memory on kernel command line must be followed by 'G' or 'M'\n",
               guestfs_int_program_name);
      exit (EXIT_FAILURE);
    }
  }

  p = get_cmdline_key (cmdline, "p2v.disks");
  if (p) {
    CLEANUP_FREE char *t;

    t = strdup (p);
    guestfs_int_free_string_list (config->disks);
    config->disks = guestfs_int_split_string (',', t);
  }

  p = get_cmdline_key (cmdline, "p2v.removable");
  if (p) {
    CLEANUP_FREE char *t;

    t = strdup (p);
    guestfs_int_free_string_list (config->removable);
    config->removable = guestfs_int_split_string (',', t);
  }

  p = get_cmdline_key (cmdline, "p2v.interfaces");
  if (p) {
    CLEANUP_FREE char *t;

    t = strdup (p);
    guestfs_int_free_string_list (config->interfaces);
    config->interfaces = guestfs_int_split_string (',', t);
  }

  p = get_cmdline_key (cmdline, "p2v.network");
  if (p) {
    CLEANUP_FREE char *t;

    t = strdup (p);
    guestfs_int_free_string_list (config->network_map);
    config->network_map = guestfs_int_split_string (',', t);
  }

  p = get_cmdline_key (cmdline, "p2v.o");
  if (p) {
    free (config->output);
    config->output = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.oa");
  if (p) {
    if (STREQ (p, "sparse"))
      config->output_allocation = OUTPUT_ALLOCATION_SPARSE;
    else if (STREQ (p, "preallocated"))
      config->output_allocation = OUTPUT_ALLOCATION_PREALLOCATED;
    else
      fprintf (stderr, "%s: warning: don't know what p2v.oa=%s means\n",
               guestfs_int_program_name, p);
  }

  p = get_cmdline_key (cmdline, "p2v.oc");
  if (p) {
    free (config->output_connection);
    config->output_connection = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.of");
  if (p) {
    free (config->output_format);
    config->output_format = strdup (p);
  }

  p = get_cmdline_key (cmdline, "p2v.os");
  if (p) {
    free (config->output_storage);
    config->output_storage = strdup (p);
  }

  /* Undocumented command line tool used for testing command line parsing. */
  p = get_cmdline_key (cmdline, "p2v.dump_config_and_exit");
  if (p) {
    print_config (config, stdout);
    exit (EXIT_SUCCESS);
  }

  /* Some disks must have been specified for conversion. */
  if (config->disks == NULL || guestfs_int_count_strings (config->disks) == 0) {
    fprintf (stderr, "%s: error: no non-removable disks were discovered on this machine.\n",
             guestfs_int_program_name);
    fprintf (stderr, "virt-p2v looked in /sys/block and in p2v.disks on the kernel command line.\n");
    fprintf (stderr, "This is a fatal error and virt-p2v cannot continue.\n");
    exit (EXIT_FAILURE);
  }

  /* Perform the conversion in text mode. */
  if (start_conversion (config, notify_ui_callback) == -1) {
    const char *err = get_conversion_error ();

    fprintf (stderr, "%s: error during conversion: %s\n",
             guestfs_int_program_name, err);

    p = get_cmdline_key (cmdline, "p2v.fail");
    if (p)
      run_command (config->verbose, "p2v.fail", p);

    exit (EXIT_FAILURE);
  }

  p = get_cmdline_key (cmdline, "p2v.post");
  if (!p) {
    if (geteuid () == 0 && cmdline_source == CMDLINE_SOURCE_PROC_CMDLINE)
      p = "poweroff";
  }
  if (p)
    run_command (config->verbose, "p2v.post", p);
}
Ejemplo n.º 12
0
int
run_glob (const char *cmd, size_t argc, char *argv[])
{
  /* For 'glob cmd foo /s* /usr/s*' this could be:
   *
   * (globs[0]) globs[1]  globs[1]  globs[2]
   * (cmd)      foo       /sbin     /usr/sbin
   *                      /srv      /usr/share
   *                      /sys      /usr/src
   *
   * and then we call every combination (ie. 1x3x3) of
   * argv[1-].
   */
  CLEANUP_FREE char ***globs = NULL;
  CLEANUP_FREE size_t *posn = NULL;
  CLEANUP_FREE size_t *count = NULL;
  size_t i;
  int r = 0;

  globs = malloc (sizeof (char **) * argc);
  posn = malloc (sizeof (size_t) * argc);
  count = malloc (sizeof (size_t) * argc);
  if (globs == NULL || posn == NULL || count == NULL) {
    perror ("malloc");
    return -1;
  }

  if (argc < 1) {
    fprintf (stderr, _("use 'glob command [args...]'\n"));
    return -1;
  }

  /* This array will record the current execution position
   * in the Cartesian product.
   * NB. globs[0], posn[0], count[0] are ignored.
   */
  for (i = 1; i < argc; ++i)
    posn[i] = 0;
  for (i = 1; i < argc; ++i)
    globs[i] = NULL;

  for (i = 1; i < argc; ++i) {
    char **pp;

    /* If it begins with "/dev/" then treat it as a globbable device
     * name.
     */
    if (STRPREFIX (argv[i], "/dev/")) {
      pp = expand_devicename (g, argv[i]);
      if (pp == NULL) {
        r = -1;
        goto error;
      }
    }
    /* If it begins with "/" it might be a globbable pathname. */
    else if (argv[i][0] == '/') {
      pp = expand_pathname (g, argv[i]);
      if (pp == NULL) {
        r = -1;
        goto error;
      }
    }
    /* Doesn't begin with '/' */
    else {
      pp = single_element_list (argv[i]);
      if (pp == NULL) {
        r = -1;
        goto error;
      }
    }

    globs[i] = pp;
    count[i] = guestfs_int_count_strings (pp);
  }

  /* Issue the commands. */
  if (glob_issue (argv[0], argc, globs, posn, count, &r) == -1) {
    r = -1;
    goto error;
  }

  /* Free resources. */
 error:
  for (i = 1; i < argc; ++i)
    if (globs[i])
      guestfs_int_free_string_list (globs[i]);
  return r;
}
Ejemplo n.º 13
0
int
main (int argc, char *argv[])
{
  gboolean gui_possible;
  int c;
  int option_index;
  char **cmdline = NULL;
  int cmdline_source = 0;
  struct config *config = new_config ();

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEBASEDIR);
  textdomain (PACKAGE);

  /* There is some raciness between slow devices being discovered by
   * the kernel and udev and virt-p2v running.  This is a partial
   * workaround, but a real fix involves handling hotplug events
   * (possible in GUI mode, not easy in kernel mode).
   */
  udevadm_settle ();

#if ! GLIB_CHECK_VERSION(2,32,0)
  /* In glib2 < 2.32 you had to call g_thread_init().  In later glib2
   * that is not required and should not be called.
   */
  if (glib_check_version (2, 32, 0) != NULL) /* This checks < 2.32 */
    g_thread_init (NULL);
#endif
  gdk_threads_init ();
  gdk_threads_enter ();
  gui_possible = gtk_init_check (&argc, &argv);

  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, "cmdline")) {
        cmdline = parse_cmdline_string (optarg);
        cmdline_source = CMDLINE_SOURCE_COMMAND_LINE;
      }
      else
        error (EXIT_FAILURE, 0,
               _("unknown long option: %s (%d)"),
               long_options[option_index].name, option_index);
      break;

    case 'v':
      config->verbose = 1;
      break;

    case 'V':
      printf ("%s %s\n", guestfs_int_program_name, PACKAGE_VERSION_FULL);
      exit (EXIT_SUCCESS);

    case HELP_OPTION:
      usage (EXIT_SUCCESS);

    default:
      usage (EXIT_FAILURE);
    }
  }

  if (optind != argc) {
    fprintf (stderr, _("%s: unused arguments on the command line\n"),
             guestfs_int_program_name);
    usage (EXIT_FAILURE);
  }

  set_config_defaults (config);

  /* Parse /proc/cmdline (if it exists) or use the --cmdline parameter
   * to initialize the configuration.  This allows defaults to be pass
   * using the kernel command line, with additional GUI configuration
   * later.
   */
  if (cmdline == NULL) {
    cmdline = parse_proc_cmdline ();
    if (cmdline != NULL)
      cmdline_source = CMDLINE_SOURCE_PROC_CMDLINE;
  }

  if (cmdline)
    update_config_from_kernel_cmdline (config, cmdline);

  /* If p2v.server exists, then we use the non-interactive kernel
   * conversion.  Otherwise we run the GUI.
   */
  if (config->server != NULL)
    kernel_conversion (config, cmdline, cmdline_source);
  else {
    if (!gui_possible)
      error (EXIT_FAILURE, 0,
             _("gtk_init_check returned false, indicating that\n"
               "a GUI is not possible on this host.  Check X11, $DISPLAY etc."));
    gui_conversion (config);
  }

  guestfs_int_free_string_list (cmdline);

  exit (EXIT_SUCCESS);
}