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