./PaxHeaders/virt-p2v-1.42.30000644000000000000000000000013214321270274012432 xustar0030 mtime=1665495228.521332068 30 atime=1665495228.547331902 30 ctime=1665495228.521332068 virt-p2v-1.42.3/0000755000175000017500000000000014321270274014156 5ustar00rjonesrjones00000000000000virt-p2v-1.42.3/PaxHeaders/ssh.c0000644000000000000000000000013214321267767013330 xustar0030 mtime=1665495031.276573678 30 atime=1665495044.541493365 30 ctime=1665495228.436332611 virt-p2v-1.42.3/ssh.c0000644000175000017500000010620614321267767015141 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2022 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * This file handles the ssh connections to the conversion server. * * virt-p2v will open several connections over the lifetime of * the conversion process. * * In C, it will first open a connection (to check it * is possible) and query virt-v2v on the server to ensure it exists, * it is the right version, and so on. This connection is then * closed, because in the GUI case we don't want to deal with keeping * it alive in case the administrator has set up an autologout. * * Once we start conversion, we will open a control connection to send * the libvirt configuration data and to start up virt-v2v, and we * will open up one data connection per local hard disk. The data * connection(s) have a reverse port forward to the local NBD server * which is serving the content of that hard disk. The remote port * for each data connection is assigned by ssh. See * C and C. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ignore-value.h" #include "miniexpect.h" #include "p2v.h" #define SSH_TIMEOUT 60 /* seconds */ char *v2v_version = NULL; char **input_drivers = NULL; char **output_drivers = NULL; static void free_globals (void) __attribute__((destructor)); static void free_globals (void) { pcre2_substring_free ((PCRE2_UCHAR *)v2v_version); } static char *ssh_error; static void set_ssh_error (const char *fs, ...) __attribute__((format(printf,1,2))); static void set_ssh_error (const char *fs, ...) { va_list args; char *msg; int len; va_start (args, fs); len = vasprintf (&msg, fs, args); va_end (args); if (len < 0) error (EXIT_FAILURE, errno, "vasprintf (original error format string: %s)", fs); free (ssh_error); ssh_error = msg; } const char * get_ssh_error (void) { return ssh_error; } /* Like set_ssh_error, but for errors that aren't supposed to happen. */ #define set_ssh_internal_error(fs, ...) \ set_ssh_error ("%s:%d: internal error: " fs, __FILE__, __LINE__, \ ##__VA_ARGS__) #define set_ssh_mexp_error(fn) \ set_ssh_internal_error ("%s: %m", fn) #define set_ssh_pcre_error() \ set_ssh_internal_error ("pcre error: %d\n", mexp_get_pcre_error (h)) #define set_ssh_unexpected_eof(fs, ...) \ set_ssh_error ("remote server closed the connection unexpectedly, " \ "waiting for: " fs, ##__VA_ARGS__) #define set_ssh_unexpected_timeout(fs, ...) \ set_ssh_error ("remote server timed out unexpectedly, " \ "waiting for: " fs, ##__VA_ARGS__) static void compile_regexps (void) __attribute__((constructor)); static void free_regexps (void) __attribute__((destructor)); static pcre2_code *password_re; static pcre2_code *ssh_message_re; static pcre2_code *sudo_password_re; static pcre2_code *prompt_re; static pcre2_code *version_re; static pcre2_code *feature_libguestfs_rewrite_re; static pcre2_code *feature_colours_option_re; static pcre2_code *feature_input_re; static pcre2_code *feature_output_re; static pcre2_code *portfwd_re; static void compile_regexps (void) { int errorcode; PCRE2_SIZE offset; char errormsg[256]; #define COMPILE(re,pattern) \ do { \ re = pcre2_compile ((PCRE2_SPTR) (pattern), \ PCRE2_ZERO_TERMINATED, \ 0, &errorcode, &offset, NULL); \ if (re == NULL) { \ pcre2_get_error_message (errorcode, \ (PCRE2_UCHAR *) errormsg, sizeof errormsg); \ ignore_value (write (2, errormsg, strlen (errormsg))); \ abort (); \ } \ } while (0) COMPILE (password_re, "password:"); /* Note that (?:.)* is required in order to work around a problem * with partial matching and PCRE in RHEL 5. */ COMPILE (ssh_message_re, "(ssh: (?:.)*)"); COMPILE (sudo_password_re, "sudo: a password is required"); /* The magic synchronization strings all match this expression. See * start_ssh function below. */ COMPILE (prompt_re, "###((?:[0123456789abcdefghijklmnopqrstuvwxyz]){8})### "); /* Note that (?:.)* is required in order to work around a problem * with partial matching and PCRE in RHEL 5. */ COMPILE (version_re, "virt-v2v ([1-9](?:.)*)"); COMPILE (feature_libguestfs_rewrite_re, "libguestfs-rewrite"); COMPILE (feature_colours_option_re, "colours-option"); /* The input and output regexps must match the same pattern in * v2v/modules_list.ml. */ COMPILE (feature_input_re, "input:((?:[-\\w])+)"); COMPILE (feature_output_re, "output:((?:[-\\w])+)"); COMPILE (portfwd_re, "Allocated port ((?:\\d)+) for remote forward"); } static void free_regexps (void) { pcre2_code_free (password_re); pcre2_code_free (ssh_message_re); pcre2_code_free (sudo_password_re); pcre2_code_free (prompt_re); pcre2_code_free (version_re); pcre2_code_free (feature_libguestfs_rewrite_re); pcre2_code_free (feature_colours_option_re); pcre2_code_free (feature_input_re); pcre2_code_free (feature_output_re); pcre2_code_free (portfwd_re); } /** * Download URL to local file using the external 'curl' command. */ static int curl_download (const char *url, const char *local_file) { char curl_config_file[] = "/tmp/curl.XXXXXX"; int fd; size_t i, len; FILE *fp; gboolean ret; const char *argv[] = { "curl", "-f", "-s", "-S", "-o", local_file, "-K", curl_config_file, NULL }; CLEANUP_FREE char *stderr = NULL; gint exit_status; GError *gerror = NULL; /* Use a secure curl config file because escaping is easier. */ fd = mkstemp (curl_config_file); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp: %s", curl_config_file); fp = fdopen (fd, "w"); if (fp == NULL) error (EXIT_FAILURE, errno, "fdopen: %s", curl_config_file); fprintf (fp, "url = \""); len = strlen (url); for (i = 0; i < len; ++i) { switch (url[i]) { case '\\': fprintf (fp, "\\\\"); break; case '"': fprintf (fp, "\\\""); break; case '\t': fprintf (fp, "\\t"); break; case '\n': fprintf (fp, "\\n"); break; case '\r': fprintf (fp, "\\r"); break; case '\v': fprintf (fp, "\\v"); break; default: fputc (url[i], fp); } } fprintf (fp, "\"\n"); fclose (fp); /* Run curl to download the URL to a file. */ ret = g_spawn_sync (NULL, /* working directory; inherit */ (gchar **) argv, NULL, /* environment; inherit */ G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL, NULL, NULL, /* no child setup */ NULL, &stderr, &exit_status, &gerror); /* unlink (curl_config_file); - useful for debugging */ if (!ret) { set_ssh_error ("g_spawn_sync: %s: %s", url, gerror->message); g_error_free (gerror); return -1; } /* Did curl subprocess fail? */ if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) != 0) { set_ssh_error ("%s: %s", url, stderr); return -1; } else if (!WIFEXITED (exit_status)) { set_ssh_internal_error ("curl subprocess got a signal (%d)", exit_status); return -1; } return 0; } /** * Re-cache the Cidentity.url> if needed. */ static int cache_ssh_identity (struct config *config) { int fd; /* If it doesn't need downloading, return. */ if (config->auth.identity.url == NULL || !config->auth.identity.file_needs_update) return 0; /* Generate a random filename. */ free (config->auth.identity.file); config->auth.identity.file = strdup ("/tmp/id.XXXXXX"); if (config->auth.identity.file == NULL) error (EXIT_FAILURE, errno, "strdup"); fd = mkstemp (config->auth.identity.file); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp"); close (fd); /* Curl download URL to file. */ if (curl_download (config->auth.identity.url, config->auth.identity.file) == -1) { free (config->auth.identity.file); config->auth.identity.file = NULL; config->auth.identity.file_needs_update = 1; return -1; } return 0; } /* GCC complains about the argv array in the next function which it * thinks might grow to an unbounded size. Since we control * extra_args, this is not in fact a problem. */ #if P2V_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstack-usage=" #endif /** * Start ssh subprocess with the standard arguments and possibly some * optional arguments. Also handles authentication. */ static mexp_h * start_ssh (unsigned spawn_flags, struct config *config, char **extra_args, int wait_prompt) { size_t i = 0; const size_t MAX_ARGS = 64 + (extra_args != NULL ? guestfs_int_count_strings (extra_args) : 0); const char *argv[MAX_ARGS]; char port_str[64]; char connect_timeout_str[128]; mexp_h *h; CLEANUP_PCRE2_MATCH_DATA pcre2_match_data *match_data = pcre2_match_data_create (4, NULL); int saved_timeout; int using_password_auth; size_t count; if (cache_ssh_identity (config) == -1) return NULL; /* Are we using password or identity authentication? */ using_password_auth = config->auth.identity.file == NULL; ADD_ARG (argv, i, "ssh"); ADD_ARG (argv, i, "-p"); /* Port. */ snprintf (port_str, sizeof port_str, "%d", config->remote.port); ADD_ARG (argv, i, port_str); ADD_ARG (argv, i, "-l"); /* Username. */ ADD_ARG (argv, i, config->auth.username ? config->auth.username : "root"); ADD_ARG (argv, i, "-o"); /* Host key will always be novel. */ ADD_ARG (argv, i, "StrictHostKeyChecking=no"); ADD_ARG (argv, i, "-o"); /* ConnectTimeout */ snprintf (connect_timeout_str, sizeof connect_timeout_str, "ConnectTimeout=%d", SSH_TIMEOUT); ADD_ARG (argv, i, connect_timeout_str); ADD_ARG (argv, i, "-o"); /* Send ping packets every 5 mins to sshd. */ ADD_ARG (argv, i, "ServerAliveInterval=300"); ADD_ARG (argv, i, "-o"); ADD_ARG (argv, i, "ServerAliveCountMax=6"); if (using_password_auth) { /* Only use password authentication. */ ADD_ARG (argv, i, "-o"); ADD_ARG (argv, i, "PreferredAuthentications=keyboard-interactive,password"); } else { /* Use identity file (private key). */ ADD_ARG (argv, i, "-o"); ADD_ARG (argv, i, "PreferredAuthentications=publickey"); ADD_ARG (argv, i, "-i"); ADD_ARG (argv, i, config->auth.identity.file); } if (extra_args != NULL) { for (size_t j = 0; extra_args[j] != NULL; ++j) ADD_ARG (argv, i, extra_args[j]); } ADD_ARG (argv, i, config->remote.server); /* Conversion server. */ ADD_ARG (argv, i, NULL); #if DEBUG_STDERR fputs ("ssh command: ", stderr); for (i = 0; argv[i] != NULL; ++i) { if (i > 0) fputc (' ', stderr); fputs (argv[i], stderr); } fputc ('\n', stderr); #endif /* Create the miniexpect handle. */ h = mexp_spawnvf (spawn_flags, "ssh", (char **) argv); if (h == NULL) { set_ssh_internal_error ("ssh: mexp_spawnvf: %m"); return NULL; } #if DEBUG_STDERR mexp_set_debug_file (h, stderr); #endif /* We want the ssh ConnectTimeout to be less than the miniexpect * timeout, so that if the server is completely unresponsive we * still see the error from ssh, not a timeout from miniexpect. The * obvious solution to this is to set ConnectTimeout (above) and to * set the miniexpect timeout to be a little bit larger. */ mexp_set_timeout (h, SSH_TIMEOUT + 20); if (using_password_auth && config->auth.password && strlen (config->auth.password) > 0) { CLEANUP_PCRE2_SUBSTRING_FREE PCRE2_UCHAR *ssh_message = NULL; PCRE2_SIZE ssh_msglen; /* Wait for the password prompt. */ wait_password_again: switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = password_re }, { 101, .re = ssh_message_re }, { 0 } }, match_data)) { case 100: /* Got password prompt. */ if (mexp_printf_password (h, "%s", config->auth.password) == -1 || mexp_printf (h, "\n") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return NULL; } break; case 101: pcre2_substring_free (ssh_message); pcre2_substring_get_bynumber (match_data, 1, &ssh_message, &ssh_msglen); goto wait_password_again; case MEXP_EOF: /* This is where we get to if the user enters an incorrect or * impossible hostname or port number. Hopefully ssh printed an * error message, and we picked it up and put it in * 'ssh_message' in case 101 above. If not we have to print a * generic error instead. */ if (ssh_message) set_ssh_error ("%s", (char *) ssh_message); else set_ssh_error ("ssh closed the connection without printing an error."); mexp_close (h); return NULL; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("password prompt"); mexp_close (h); return NULL; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return NULL; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return NULL; } } if (!wait_prompt) return h; /* Ensure we are running bash, set environment variables, and * synchronize with the command prompt and set it to a known * string. There are multiple issues being solved here: * * We cannot control the initial shell prompt. It would involve * changing the remote SSH configuration (AcceptEnv). However what * we can do is to repeatedly send 'export PS1=' commands * until we synchronize with the remote shell. * * Since we parse error messages, we must set LANG=C. * * We don't know if the user is using a Bourne-like shell (eg sh, * bash) or csh/tcsh. Setting environment variables works * differently. * * We don't know how command line editing is set up * (https://bugzilla.redhat.com/1314244#c9). */ if (mexp_printf (h, "exec bash --noediting --noprofile\n") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return NULL; } saved_timeout = mexp_get_timeout_ms (h); mexp_set_timeout (h, 2); for (count = 0; count < 30; ++count) { char magic[9]; PCRE2_UCHAR *matched; PCRE2_SIZE matchlen; int r; if (guestfs_int_random_string (magic, 8) == -1) { set_ssh_internal_error ("random_string: %m"); mexp_close (h); return NULL; } /* The purpose of the '' inside the string is to ensure we don't * mistake the command echo for the prompt. */ if (mexp_printf (h, "export LANG=C PS1='###''%s''### '\n", magic) == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return NULL; } /* Wait for the prompt. */ wait_again: switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = password_re }, { 101, .re = prompt_re }, { 0 } }, match_data)) { case 100: /* Got password prompt unexpectedly. */ set_ssh_error ("Login failed. Probably the username and/or password is wrong."); mexp_close (h); return NULL; case 101: /* Got a prompt. However it might be an earlier prompt. If it * doesn't match the PS1 string we sent, then repeat the expect. */ r = pcre2_substring_get_bynumber (match_data, 1, &matched, &matchlen); if (r < 0) error (EXIT_FAILURE, 0, "pcre error reading substring (%d)", r); r = STREQ (magic, (char *) matched); pcre2_substring_free (matched); if (!r) goto wait_again; goto got_prompt; case MEXP_EOF: set_ssh_unexpected_eof ("the command prompt"); mexp_close (h); return NULL; case MEXP_TIMEOUT: /* Timeout here is not an error, since ssh may "eat" commands that * we send before the shell at the other end is ready. Just loop. */ break; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return NULL; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return NULL; } } set_ssh_error ("Failed to synchronize with remote shell after 60 seconds."); mexp_close (h); return NULL; got_prompt: mexp_set_timeout_ms (h, saved_timeout); return h; } #if P2V_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */ #pragma GCC diagnostic pop #endif /** * Upload file(s) to remote using L. * * Note that the target (directory or file) comes before the list of * local files, because the list of local files is a varargs list. * * This is a simplified version of L above. */ int scp_file (struct config *config, const char *target, const char *local, ...) { size_t i = 0; va_list args; const size_t MAX_ARGS = 64; const char *argv[MAX_ARGS]; char port_str[64]; char connect_timeout_str[128]; CLEANUP_FREE char *remote = NULL; mexp_h *h; CLEANUP_PCRE2_MATCH_DATA pcre2_match_data *match_data = pcre2_match_data_create (4, NULL); int using_password_auth; if (cache_ssh_identity (config) == -1) return -1; /* Are we using password or identity authentication? */ using_password_auth = config->auth.identity.file == NULL; ADD_ARG (argv, i, "scp"); ADD_ARG (argv, i, "-P"); /* Port. */ snprintf (port_str, sizeof port_str, "%d", config->remote.port); ADD_ARG (argv, i, port_str); ADD_ARG (argv, i, "-o"); /* Host key will always be novel. */ ADD_ARG (argv, i, "StrictHostKeyChecking=no"); ADD_ARG (argv, i, "-o"); /* ConnectTimeout */ snprintf (connect_timeout_str, sizeof connect_timeout_str, "ConnectTimeout=%d", SSH_TIMEOUT); ADD_ARG (argv, i, connect_timeout_str); if (using_password_auth) { /* Only use password authentication. */ ADD_ARG (argv, i, "-o"); ADD_ARG (argv, i, "PreferredAuthentications=keyboard-interactive,password"); } else { /* Use identity file (private key). */ ADD_ARG (argv, i, "-o"); ADD_ARG (argv, i, "PreferredAuthentications=publickey"); ADD_ARG (argv, i, "-i"); ADD_ARG (argv, i, config->auth.identity.file); } /* Source files or directories. * Strictly speaking this could abort() if the list of files is * too long, but that never happens in virt-p2v. XXX */ va_start (args, local); do ADD_ARG (argv, i, local); while ((local = va_arg (args, const char *)) != NULL); va_end (args); /* The target file or directory. We need to rewrite this as * "username@server:target". */ if (asprintf (&remote, "%s@%s:%s", config->auth.username ? config->auth.username : "root", config->remote.server, target) == -1) error (EXIT_FAILURE, errno, "asprintf"); ADD_ARG (argv, i, remote); ADD_ARG (argv, i, NULL); #if DEBUG_STDERR fputs ("scp command: ", stderr); for (i = 0; argv[i] != NULL; ++i) { if (i > 0) fputc (' ', stderr); fputs (argv[i], stderr); } fputc ('\n', stderr); #endif /* Create the miniexpect handle. */ h = mexp_spawnv ("scp", (char **) argv); if (h == NULL) { set_ssh_internal_error ("scp: mexp_spawnv: %m"); return -1; } #if DEBUG_STDERR mexp_set_debug_file (h, stderr); #endif /* We want the ssh ConnectTimeout to be less than the miniexpect * timeout, so that if the server is completely unresponsive we * still see the error from ssh, not a timeout from miniexpect. The * obvious solution to this is to set ConnectTimeout (above) and to * set the miniexpect timeout to be a little bit larger. */ mexp_set_timeout (h, SSH_TIMEOUT + 20); if (using_password_auth && config->auth.password && strlen (config->auth.password) > 0) { CLEANUP_PCRE2_SUBSTRING_FREE PCRE2_UCHAR *ssh_message = NULL; PCRE2_SIZE ssh_msglen; /* Wait for the password prompt. */ wait_password_again: switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = password_re }, { 101, .re = ssh_message_re }, { 0 } }, match_data)) { case 100: /* Got password prompt. */ if (mexp_printf_password (h, "%s", config->auth.password) == -1 || mexp_printf (h, "\n") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return -1; } break; case 101: pcre2_substring_free (ssh_message); pcre2_substring_get_bynumber (match_data, 1, &ssh_message, &ssh_msglen); goto wait_password_again; case MEXP_EOF: /* This is where we get to if the user enters an incorrect or * impossible hostname or port number. Hopefully scp printed an * error message, and we picked it up and put it in * 'ssh_message' in case 101 above. If not we have to print a * generic error instead. */ if (ssh_message) set_ssh_error ("%s", (char *) ssh_message); else set_ssh_error ("scp closed the connection without printing an error."); mexp_close (h); return -1; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("password prompt"); mexp_close (h); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return -1; } } /* Wait for the scp subprocess to finish. */ switch (mexp_expect (h, NULL, NULL)) { case MEXP_EOF: break; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("copying (scp) file"); mexp_close (h); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return -1; } if (mexp_close (h) == -1) { set_ssh_internal_error ("scp: mexp_close: %m"); return -1; } return 0; } static void add_input_driver (const char *name); static void add_output_driver (const char *name); static int compatible_version (const char *v2v_version_p); #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" /* WTF? */ #endif int test_connection (struct config *config) { mexp_h *h; int feature_libguestfs_rewrite = 0; int status; CLEANUP_PCRE2_MATCH_DATA pcre2_match_data *match_data = pcre2_match_data_create (4, NULL); PCRE2_SIZE verlen; h = start_ssh (0, config, NULL, 1); if (h == NULL) return -1; /* Clear any previous version information since we may be connecting * to a different server. */ pcre2_substring_free ((PCRE2_UCHAR *)v2v_version); v2v_version = NULL; /* Send 'virt-v2v --version' command and hope we get back a version string. * Note old virt-v2v did not understand -V option. */ if (mexp_printf (h, "%svirt-v2v --version\n", config->auth.sudo ? "sudo -n " : "") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return -1; } for (;;) { switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = version_re }, { 101, .re = sudo_password_re }, { 102, .re = prompt_re }, { 0 } }, match_data)) { case 100: /* Got version string. */ pcre2_substring_free ((PCRE2_UCHAR *)v2v_version); pcre2_substring_get_bynumber (match_data, 1, (PCRE2_UCHAR **) &v2v_version, &verlen); #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v version: %s\n", g_get_prgname (), v2v_version); #endif break; case 101: set_ssh_error ("sudo for user \"%s\" requires a password. Edit /etc/sudoers on the conversion server to ensure the \"NOPASSWD:\" option is set for this user.", config->auth.username); mexp_close (h); return -1; case 102: /* Got the prompt. */ goto end_of_version; case MEXP_EOF: set_ssh_unexpected_eof ("\"virt-v2v --version\" output"); mexp_close (h); return -1; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("\"virt-v2v --version\" output"); mexp_close (h); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return -1; } } end_of_version: /* Got the prompt but no version number. */ if (v2v_version == NULL) { set_ssh_error ("virt-v2v is not installed on the conversion server, " "or it might be a too old version."); mexp_close (h); return -1; } /* Check the version of virt-v2v is compatible with virt-p2v. */ if (!compatible_version (v2v_version)) { mexp_close (h); return -1; } /* Clear any previous driver information since we may be connecting * to a different server. */ guestfs_int_free_string_list (input_drivers); guestfs_int_free_string_list (output_drivers); input_drivers = output_drivers = NULL; /* Get virt-v2v features. See: v2v/cmdline.ml */ if (mexp_printf (h, "%svirt-v2v --machine-readable\n", config->auth.sudo ? "sudo -n " : "") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return -1; } for (;;) { PCRE2_UCHAR *driver; PCRE2_SIZE drvrlen; switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = feature_libguestfs_rewrite_re }, { 101, .re = feature_colours_option_re }, { 102, .re = feature_input_re }, { 103, .re = feature_output_re }, { 104, .re = prompt_re }, { 0 } }, match_data)) { case 100: /* libguestfs-rewrite. */ feature_libguestfs_rewrite = 1; break; case 101: /* virt-v2v supports --colours option */ #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v supports --colours option\n", g_get_prgname ()); #endif feature_colours_option = 1; break; case 102: /* input: corresponds to an -i option in virt-v2v. */ pcre2_substring_get_bynumber (match_data, 1, &driver, &drvrlen); add_input_driver ((char *) driver); pcre2_substring_free (driver); break; case 103: /* output: corresponds to an -o option in virt-v2v. */ pcre2_substring_get_bynumber (match_data, 1, &driver, &drvrlen); add_output_driver ((char *) driver); pcre2_substring_free (driver); break; case 104: /* Got prompt, so end of output. */ goto end_of_machine_readable; case MEXP_EOF: set_ssh_unexpected_eof ("\"virt-v2v --machine-readable\" output"); mexp_close (h); return -1; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("\"virt-v2v --machine-readable\" output"); mexp_close (h); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return -1; } } end_of_machine_readable: if (!feature_libguestfs_rewrite) { set_ssh_error ("Invalid output of \"virt-v2v --machine-readable\" command."); mexp_close (h); return -1; } /* Test finished, shut down ssh. */ if (mexp_printf (h, "exit\n") == -1) { set_ssh_mexp_error ("mexp_printf"); mexp_close (h); return -1; } switch (mexp_expect (h, NULL, NULL)) { case MEXP_EOF: break; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("end of ssh session"); mexp_close (h); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return -1; } status = mexp_close (h); if (status == -1) { set_ssh_internal_error ("mexp_close: %m"); return -1; } if (WIFSIGNALED (status) && WTERMSIG (status) == SIGHUP) return 0; /* not an error */ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) { set_ssh_internal_error ("unexpected close status from ssh subprocess (%d)", status); return -1; } return 0; } static void add_option (const char *type, char ***drivers, const char *name) { size_t n; if (*drivers == NULL) n = 0; else n = guestfs_int_count_strings (*drivers); n++; *drivers = realloc (*drivers, (n+1) * sizeof (char *)); if (*drivers == NULL) error (EXIT_FAILURE, errno, "malloc"); (*drivers)[n-1] = strdup (name); if ((*drivers)[n-1] == NULL) error (EXIT_FAILURE, errno, "strdup"); (*drivers)[n] = NULL; #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v supports %s driver %s\n", g_get_prgname (), type, (*drivers)[n-1]); #endif } static void add_input_driver (const char *name) { add_option ("input", &input_drivers, name); } static void add_output_driver (const char *name) { /* Ignore the 'vdsm' driver, since that should only be used by VDSM. * Ignore the 'openstack' and 'rhv-upload' drivers, since we do not * support passing all the options for them. */ if (STRNEQ (name, "vdsm") && STRNEQ (name, "openstack") && STRNEQ (name, "rhv-upload")) add_option ("output", &output_drivers, name); } static int compatible_version (const char *v2v_version_p) { unsigned v2v_major, v2v_minor; /* The major version must always be 1 or 2. */ if (!STRPREFIX (v2v_version_p, "1.") && !STRPREFIX (v2v_version_p, "2.")) { set_ssh_error ("virt-v2v major version is neither 1 nor 2 (\"%s\"), " "this version of virt-p2v is not compatible.", v2v_version_p); return 0; } /* The version of virt-v2v must be >= 1.28, just to make sure * someone isn't (a) using one of the experimental 1.27 releases * that we published during development, nor (b) using old virt-v2v. * We should remain compatible with any virt-v2v after 1.28. */ if (sscanf (v2v_version_p, "%u.%u", &v2v_major, &v2v_minor) != 2) { set_ssh_internal_error ("cannot parse virt-v2v version string (\"%s\")", v2v_version_p); return 0; } if (v2v_major == 1 && v2v_minor < 28) { set_ssh_error ("virt-v2v version is < 1.28 (\"%s\"), " "you must upgrade to virt-v2v >= 1.28 on " "the conversion server.", v2v_version_p); return 0; } return 1; /* compatible */ } mexp_h * open_data_connection (struct config *config, int local_port, int *remote_port) { mexp_h *h; char remote_arg[32]; const char *extra_args[] = { "-R", remote_arg, "-N", NULL }; PCRE2_UCHAR *port_str; PCRE2_SIZE portlen; CLEANUP_PCRE2_MATCH_DATA pcre2_match_data *match_data = pcre2_match_data_create (4, NULL); snprintf (remote_arg, sizeof remote_arg, "0:localhost:%d", local_port); h = start_ssh (0, config, (char **) extra_args, 0); if (h == NULL) return NULL; switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = portfwd_re }, { 0 } }, match_data)) { case 100: /* Ephemeral port. */ pcre2_substring_get_bynumber (match_data, 1, &port_str, &portlen); if (port_str == NULL) { set_ssh_internal_error ("strndup: %m"); mexp_close (h); return NULL; } if (sscanf ((char *) port_str, "%d", remote_port) != 1) { set_ssh_internal_error ("cannot extract the port number from '%s'", port_str); pcre2_substring_free (port_str); mexp_close (h); return NULL; } pcre2_substring_free (port_str); break; case MEXP_EOF: set_ssh_unexpected_eof ("\"ssh -R\" output"); mexp_close (h); return NULL; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("\"ssh -R\" output"); mexp_close (h); return NULL; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); mexp_close (h); return NULL; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); mexp_close (h); return NULL; } return h; } /* Wait for the prompt. */ static int wait_for_prompt (mexp_h *h) { CLEANUP_PCRE2_MATCH_DATA pcre2_match_data *match_data = pcre2_match_data_create (4, NULL); switch (mexp_expect (h, (mexp_regexp[]) { { 100, .re = prompt_re }, { 0 } }, match_data)) { case 100: /* Got the prompt. */ return 0; case MEXP_EOF: set_ssh_unexpected_eof ("command prompt"); return -1; case MEXP_TIMEOUT: set_ssh_unexpected_timeout ("command prompt"); return -1; case MEXP_ERROR: set_ssh_mexp_error ("mexp_expect"); return -1; case MEXP_PCRE_ERROR: set_ssh_pcre_error (); return -1; } return 0; } mexp_h * start_remote_connection (struct config *config, const char *remote_dir) { mexp_h *h; /* This connection is opened in cooked mode so that we can send ^C * if the conversion needs to be cancelled. However that also means * we must be careful not to accidentally send any control * characters over this connection at other times. */ h = start_ssh (MEXP_SPAWN_COOKED_MODE, config, NULL, 1); if (h == NULL) return NULL; /* Create the remote directory. */ if (mexp_printf (h, "mkdir %s\n", remote_dir) == -1) { set_ssh_mexp_error ("mexp_printf"); goto error; } if (wait_for_prompt (h) == -1) goto error; /* It's simplest to create the remote 'time' file by running the date * command, as that won't send any special control characters. */ if (mexp_printf (h, "date > %s/time\n", remote_dir) == -1) { set_ssh_mexp_error ("mexp_printf"); goto error; } if (wait_for_prompt (h) == -1) goto error; return h; error: mexp_close (h); return NULL; } virt-p2v-1.42.3/PaxHeaders/virt-p2v-make-disk.in0000644000000000000000000000013214267535425016251 xustar0030 mtime=1658764053.832410166 30 atime=1665478155.844244612 30 ctime=1665495228.405332809 virt-p2v-1.42.3/virt-p2v-make-disk.in0000644000175000017500000002062414267535425020061 0ustar00rjonesrjones00000000000000#!/bin/bash - # @configure_input@ # virt-p2v-make-disk # Copyright (C) 2014-2019 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . unset CDPATH program="virt-p2v-make-disk" version="@PACKAGE_VERSION@" prefix="@prefix@" exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" if [ -n "$VIRT_P2V_DATA_DIR" ]; then datadir="$VIRT_P2V_DATA_DIR" libdir="$VIRT_P2V_DATA_DIR" else datadir="@datadir@/virt-p2v" libdir="@libdir@/virt-p2v" fi # Parse the command line arguments. shortopts=o:vV longopts=arch:,help,short-options,inject-ssh-identity:,install:,long-options,no-warn-if-partition,output:,verbose,version TEMP=`getopt \ -o "$shortopts" \ --long "$longopts" \ -n $program -- "$@"` if [ $? != 0 ]; then echo "$program: problem parsing the command line arguments" exit 1 fi eval set -- "$TEMP" output= upload= verbose= declare -a passthru usage () { echo "Usage:" echo " $program [--options] -o /dev/sdX [os-version]" echo echo "Read $program(1) man page for more information." exit $1 } while true; do case "$1" in --arch) arch="$2" shift 2;; --inject-ssh-identity) upload="--upload $2:/var/tmp/id_rsa" shift 2;; -o|--output) output="$2" shift 2;; -v|--verbose) set +x verbose=1 shift;; # virt-builder parameters that are passed through. --install) passthru[${#passthru[*]}]="$1" passthru[${#passthru[*]}]="$2" shift 2;; --no-warn-if-partition) passthru[${#passthru[*]}]="$1" shift;; # help etc. --help) usage 0;; -V|--version) echo "$program $version" exit 0;; --short-options) echo -n "$shortopts" | @SED@ -e 's/://g' -e 's/\(.\)/-\1\n/g' exit 0;; --long-options) echo "$longopts" | @SED@ -e 's/,/\n/g' -e 's/:$//mg' -e 's/\(.*\)/--\1/mg' | grep -v -E -- "--(short|long)-options" exit 0;; --) shift break;; *) echo "internal error ($1)" exit 1;; esac done if [ -z "$output" ]; then echo "$program: You must set the -o (--output) option." exit 1 fi if [ $# -gt 1 ]; then echo "$program: Too many parameters. See $program(1)." exit 1 fi if [ $# -eq 1 ]; then osversion="$1" else # If osversion was not set, then we must guess a good value # based on the host distro. if test -f /etc/os-release; then osversion="`. /etc/os-release && echo ${ID}-${VERSION_ID}`" fi if [ "x$osversion" = "x" ]; then echo "$program: unable to guess a suitable os-version." echo "You must supply one on the command line and output of 'virt-builder -l'." echo "See $program(1) for further details." exit 1 fi fi if [ -n "$arch" ]; then arch_option="--arch $arch" virt_p2v_xz_binary="$libdir/virt-p2v.$arch.xz" else virt_p2v_xz_binary="$libdir/virt-p2v.xz" fi if [ ! -f "$virt_p2v_xz_binary" ]; then echo "$program: cannot find $virt_p2v_xz_binary" if [ -n "$arch" ]; then echo "You used the '--arch' option, so it’s likely that you will need to build" echo "a virt-p2v.$arch binary yourself." echo "See p2v-building(1) section BUILDING i686 32 BIT VIRT-P2V for help." fi exit 1 fi # Create a temporary directory and clean it up when we finish. tmpdir="$(mktemp -d)" cleanup () { rm -rf $tmpdir } trap cleanup INT QUIT TERM EXIT ERR # Uncompress the virt-p2v binary into tmpdir. virt_p2v_binary="$tmpdir/virt-p2v" xzcat "$virt_p2v_xz_binary" > "$virt_p2v_binary" # Variations depending on the target distro. The main difference # is in the list of distro packages we add to the base appliance. case "$osversion" in centos-*|fedora-*|rhel-*|scientificlinux-*|oraclelinux-*) depsfile="$datadir/dependencies.redhat" cat > $tmpdir/p2v.conf <<'EOF' add_drivers+=" usb-storage " EOF cat > $tmpdir/post-install <<'EOF' #!/bin/bash # Rebuild the initramfs. latest_version="$(cd /lib/modules; ls -1vr | head -1)" dracut -v -f --kver $latest_version EOF # Double quotes because we want $tmpdir to be expanded: extra_args=" --selinux-relabel --upload $tmpdir/p2v.conf:/etc/dracut.conf.d/ --run $tmpdir/post-install " ;; debian-*|ubuntu-*) depsfile="$datadir/dependencies.debian" cat > $tmpdir/policy-rc.d <<'EOF' #!/bin/sh # Avoid running daemons during the upgrade/installation exit 101 EOF chmod +x $tmpdir/policy-rc.d # Double quotes because we want $tmpdir to be expanded: preinstall_args=" --upload $tmpdir/policy-rc.d:/usr/sbin/policy-rc.d " final_args=" --delete /usr/sbin/policy-rc.d " ;; archlinux-*) depsfile="$datadir/dependencies.archlinux" ;; opensuse-*|suse-*) depsfile="$datadir/dependencies.suse" ;; *) echo "$program: internal error: could not work out the Linux distro from '$osversion'" exit 1 esac # Virt-builder requires the dependencies to be comma-separated with # no spaces. The $depsfile is one dependency per line. if [ ! -f "$depsfile" ]; then echo "$program: cannot find dependencies file ($depsfile)" exit 1 fi install= while read line; do if [ -n "$line" ]; then if [ -z "$install" ]; then install="$line" else install="$install,$line" fi fi done < $depsfile # Add -v -x if we're in verbose mode. if [ "x$verbose" = "x1" ]; then verbose_option="-v -x" fi # Run virt-builder. Note we controversially assume systemd here. We # could provide a sysvinit fallback if required. # The manual 'hostname' invocation is needed to set the hostname # also for the appliance itself, so scriptlets can properly use # the hostname we want. virt-builder "$osversion" \ $verbose_option \ --output "$output" \ $arch_option \ $preinstall_args \ --hostname p2v.local \ --run-command 'hostname p2v.local' \ --run-command 'dnf -y update --exclude=kernel\*' \ --install "$install" \ --root-password password:p2v \ --upload "$datadir"/issue:/etc/issue \ --upload "$datadir"/issue:/etc/issue.net \ --mkdir /usr/bin \ --upload "$virt_p2v_binary":/usr/bin/virt-p2v \ --chmod 0755:/usr/bin/virt-p2v \ --upload "$datadir"/launch-virt-p2v:/usr/bin/ \ --chmod 0755:/usr/bin/launch-virt-p2v \ --upload "$datadir"/p2v.service:/etc/systemd/system/ \ --mkdir /etc/systemd/system/multi-user.target.wants \ --link /etc/systemd/system/p2v.service:/etc/systemd/system/multi-user.target.wants/p2v.service \ --edit '/lib/systemd/system/getty@.service: s/^ExecStart=(.*)/ExecStart=$1 -a root/ ' \ --edit '/etc/systemd/logind.conf: s/^[Login]/[Login]\nReserveVT=1\n/ ' \ $upload \ $extra_args \ "${passthru[@]}" \ $final_args # We have to do this so the cleanup() handler runs. exit $? virt-p2v-1.42.3/PaxHeaders/COPYING.LIB0000644000000000000000000000013214205675260014017 xustar0030 mtime=1645705904.587187577 30 atime=1665494789.828055985 30 ctime=1665495228.418332726 virt-p2v-1.42.3/COPYING.LIB0000644000175000017500000006364214205675260015636 0ustar00rjonesrjones00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! virt-p2v-1.42.3/PaxHeaders/test-virt-p2v-docs.sh0000644000000000000000000000013214205675260016307 xustar0030 mtime=1645705904.595187498 30 atime=1665478273.214549561 30 ctime=1665495228.439332591 virt-p2v-1.42.3/test-virt-p2v-docs.sh0000755000175000017500000000143214205675260020116 0ustar00rjonesrjones00000000000000#!/bin/bash - # libguestfs # Copyright (C) 2016 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set -e $TEST_FUNCTIONS skip_if_skipped $top_srcdir/podcheck.pl $srcdir/virt-p2v.pod virt-p2v virt-p2v-1.42.3/PaxHeaders/subdir-rules.mk0000644000000000000000000000013214205675260015330 xustar0030 mtime=1645705904.595187498 30 atime=1665478158.826227022 30 ctime=1665495228.415332744 virt-p2v-1.42.3/subdir-rules.mk0000644000175000017500000000412514205675260017136 0ustar00rjonesrjones00000000000000# libguestfs # Copyright (C) 2013 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # subdir-rules.mk should be included in every *subdirectory* Makefile.am. # Editor backup files CLEANFILES = *~ *.bak # Patch original and reject files. CLEANFILES += *.orig *.rej # Manual pages - these are all generated from *.pod, so the # pages themselves should all be removed by 'make clean'. CLEANFILES += *.1 *.3 *.5 *.8 # Stamp files used when generating man pages. CLEANFILES += stamp-*.pod # Files that should be universally removed by 'make distclean'. DISTCLEANFILES = stamp-* # custom silent rules guestfs_am_v_podwrapper = $(guestfs_am_v_podwrapper_@AM_V@) guestfs_am_v_podwrapper_ = $(guestfs_am_v_podwrapper_@AM_DEFAULT_V@) guestfs_am_v_podwrapper_0 = @echo " POD " $@; # Test shell scripts should use '$TEST_FUNCTIONS' to get a predefined # set of helper functions for running tests (see # tests/test-functions.sh). # # Notes: # # (1) This is in fact a single command all on one line. The variables # are evaluated in test-functions.sh. # # (2) We use absolute paths here and in test-functions.sh so that the # test can change directory freely. But we also include the # non-absolute values so they can be used by the test script itself. export TEST_FUNCTIONS := \ source $(abs_top_srcdir)/test-functions.sh \ abs_srcdir="$(abs_srcdir)" \ abs_builddir="$(abs_builddir)" \ top_srcdir="$(top_srcdir)" \ top_builddir="$(top_builddir)" \ abs_top_srcdir="$(abs_top_srcdir)" \ abs_top_builddir="$(abs_top_builddir)" virt-p2v-1.42.3/PaxHeaders/aclocal.m40000644000000000000000000000013214321227016014206 xustar0030 mtime=1665478158.271230296 30 atime=1665478158.371229706 30 ctime=1665495228.401332834 virt-p2v-1.42.3/aclocal.m40000644000175000017500000015353514321227016016026 0ustar00rjonesrjones00000000000000# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, [m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 11 (pkg-config-0.29.1) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES # Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) virt-p2v-1.42.3/PaxHeaders/cpuid.c0000644000000000000000000000013014314553633013625 xustar0029 mtime=1664276379.71730762 29 atime=1665478120.02946287 30 ctime=1665495228.426332674 virt-p2v-1.42.3/cpuid.c0000644000175000017500000001231714314553633015437 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2019 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * Find CPU vendor, topology and some CPU flags. * * lscpu (from util-linux) provides CPU vendor, topology and flags. * * ACPI can be read by seeing if F exists. * * CPU model is essentially impossible to get without using libvirt, * but we cannot use libvirt for the reasons outlined in this message: * https://www.redhat.com/archives/libvirt-users/2017-March/msg00071.html * * Note that #vCPUs and amount of RAM is handled by F. */ #include #include #include #include #include #include #include #include #include "ignore-value.h" #include "p2v.h" static void free_cpu_config (struct cpu_config *cpu) { if (cpu->vendor) free (cpu->vendor); if (cpu->model) free (cpu->model); memset (cpu, 0, sizeof *cpu); } /** * Get the output of lscpu as a list of (key, value) pairs (as a * flattened list of strings). */ static char ** get_lscpu (void) { const char *cmd; CLEANUP_PCLOSE FILE *fp = NULL; CLEANUP_FREE char *line = NULL; ssize_t len; size_t buflen = 0; char **ret = NULL; size_t ret_size = 0; cmd = "lscpu"; fp = popen (cmd, "re"); if (fp == NULL) { perror (cmd); return NULL; } ret = malloc (sizeof (char *)); if (ret == NULL) error (EXIT_FAILURE, errno, "malloc"); ret[0] = NULL; while (errno = 0, (len = getline (&line, &buflen, fp)) != -1) { char *p; char *key, *value; if (len > 0 && line[len-1] == '\n') line[len-1] = '\0'; /* Split the line at the first ':' character. */ p = strchr (line, ':'); if (p == NULL) continue; *p = '\0'; key = strdup (line); /* Skip leading whitespace in the value. */ for (++p; *p && g_ascii_isspace (*p); ++p) ; value = strdup (p); /* Add key and value to the list, and trailing NULL pointer. */ ret_size += 2; ret = realloc (ret, (ret_size + 1) * sizeof (char *)); if (ret == NULL) error (EXIT_FAILURE, errno, "realloc"); ret[ret_size-2] = key; ret[ret_size-1] = value; ret[ret_size] = NULL; } if (errno) { perror (cmd); guestfs_int_free_string_list (ret); return NULL; } return ret; } /** * Read a single field from lscpu output. * * If the field does not exist, returns C. */ static const char * get_field (char **lscpu, const char *key) { size_t i; for (i = 0; lscpu[i] != NULL; i += 2) { if (STREQ (lscpu[i], key)) return lscpu[i+1]; } return NULL; } /** * Read the CPU vendor from lscpu output. */ static void get_vendor (char **lscpu, struct cpu_config *cpu) { const char *vendor = get_field (lscpu, "Vendor ID"); if (vendor) { /* Note this mapping comes from /usr/share/libvirt/cpu_map.xml */ if (STREQ (vendor, "GenuineIntel")) cpu->vendor = strdup ("Intel"); else if (STREQ (vendor, "AuthenticAMD")) cpu->vendor = strdup ("AMD"); /* Currently aarch64 lscpu has no Vendor ID XXX. */ } } /** * Read the CPU topology from a separate lscpu invocation. */ void get_cpu_topology (struct cpu_topo *topo) { CLEANUP_FREE_STRING_LIST char **lscpu = NULL; lscpu = get_lscpu (); if (lscpu != NULL) { const char *sockets, *cores, *threads; sockets = get_field (lscpu, "Socket(s)"); cores = get_field (lscpu, "Core(s) per socket"); threads = get_field (lscpu, "Thread(s) per core"); if (sockets && cores && threads) { ignore_value (sscanf (sockets, "%u", &topo->sockets)); ignore_value (sscanf (cores, "%u", &topo->cores)); ignore_value (sscanf (threads, "%u", &topo->threads)); return; } } topo->sockets = 1; topo->cores = 1; topo->threads = 1; } /** * Read some important flags from lscpu output. */ static void get_flags (char **lscpu, struct cpu_config *cpu) { const char *flags; flags = get_field (lscpu, "Flags"); if (flags) { cpu->apic = strstr (flags, " apic ") != NULL; cpu->pae = strstr (flags, " pae ") != NULL; /* aarch64 /proc/cpuinfo has a "Features" field, but lscpu does * not expose it. However aarch64 Features does not contain any * of the interesting flags above. */ } } /** * Find out if the system uses ACPI. */ static void get_acpi (struct cpu_config *cpu) { cpu->acpi = access ("/sys/firmware/acpi", F_OK) == 0; } void get_cpu_config (struct cpu_config *cpu) { CLEANUP_FREE_STRING_LIST char **lscpu = NULL; free_cpu_config (cpu); lscpu = get_lscpu (); if (lscpu != NULL) { get_vendor (lscpu, cpu); get_flags (lscpu, cpu); } get_acpi (cpu); } virt-p2v-1.42.3/PaxHeaders/gui.c0000644000000000000000000000013214321226753013305 xustar0030 mtime=1665478123.019444281 30 atime=1665478123.022444263 30 ctime=1665495228.428332661 virt-p2v-1.42.3/gui.c0000644000175000017500000023471414321226753015124 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2019 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * This file implements almost all of the virt-p2v graphical user * interface (GUI). * * The GUI has three main dialogs: * * =over 4 * * =item Connection dialog * * The connection dialog is the one shown initially. It asks the user * to type in the login details for the remote conversion server and * invites the user to test the ssh connection. * * =item Conversion dialog * * The conversion dialog asks for information about the target VM * (eg. the number of vCPUs required), and about what to convert * (eg. which network interfaces should be copied and which should be * ignored). * * =item Running dialog * * The running dialog is displayed when the P2V process is underway. * It mainly displays the virt-v2v debug messages. * * =back * * Note that the other major dialog (C<"Configure network ...">) is * handled entirely by NetworkManager's L * program and has nothing to do with this code. * * This file is written in a kind of "pseudo-Gtk" that currently targets Gtk * 3.22 exclusively, but may later be extended to a broader Gtk version range. * This is done using a few macros to implement old C functions or map * them to newer functions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* errors in */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" #if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */ #pragma GCC diagnostic ignored "-Wshift-overflow" #endif #include #pragma GCC diagnostic pop #include "ignore-value.h" #include "p2v.h" /* See note about "pseudo-Gtk" above. */ #include "gui-gtk3-compat.h" /* Maximum vCPUs and guest memory that we will allow users to set. * These limits come from * https://access.redhat.com/articles/rhel-kvm-limits */ #define MAX_SUPPORTED_VCPUS 160 #define MAX_SUPPORTED_MEMORY_MB (UINT64_C (4000 * 1024)) static void create_connection_dialog (struct config *); static void create_conversion_dialog (struct config *config, const char * const *disks, const char * const *removable); static void create_running_dialog (void); static void show_connection_dialog (void); static void show_conversion_dialog (void); static void show_running_dialog (void); static void set_info_label (void); /* The connection dialog. */ static GtkWidget *conn_dlg, *server_entry, *port_entry, *username_entry, *password_entry, *identity_entry, *sudo_button, *spinner_hbox, *spinner, *spinner_message, *next_button; /* The conversion dialog. */ static GtkWidget *conv_dlg, *guestname_entry, *vcpu_topo, *vcpus_entry, *memory_entry, *vcpus_warning, *memory_warning, *target_warning_label, *o_combo, *oc_entry, *os_entry, *of_entry, *oa_combo, *info_label, *disks_list, *removable_list, *interfaces_list; static int vcpus_entry_when_last_sensitive; /* The running dialog which is displayed when virt-v2v is running. */ static GtkWidget *run_dlg, *v2v_output_sw, *v2v_output, *log_label, *status_label, *cancel_button, *shutdown_button; /* Colour tags used in the v2v_output GtkTextBuffer. */ static GtkTextTag *v2v_output_tags[16]; /** * The entry point from the main program. * * Note that C etc have already been called in C
. */ void gui_conversion (struct config *config, const char * const *disks, const char * const *removable) { /* Create the dialogs. */ create_connection_dialog (config); create_conversion_dialog (config, disks, removable); create_running_dialog (); /* Start by displaying the connection dialog. */ show_connection_dialog (); gtk_main (); } /*----------------------------------------------------------------------*/ /* Connection dialog. */ static void username_changed_callback (GtkWidget *w, gpointer data); static void password_or_identity_changed_callback (GtkWidget *w, gpointer data); static void test_connection_clicked (GtkWidget *w, gpointer data); static void *test_connection_thread (void *data); static gboolean start_spinner (gpointer user_data); static gboolean stop_spinner (gpointer user_data); static gboolean test_connection_error (gpointer user_data); static gboolean test_connection_ok (gpointer user_data); static void configure_network_button_clicked (GtkWidget *w, gpointer data); static void xterm_button_clicked (GtkWidget *w, gpointer data); static void about_button_clicked (GtkWidget *w, gpointer data); static void connection_next_clicked (GtkWidget *w, gpointer data); static void repopulate_output_combo (struct config *config); /** * Create the connection dialog. * * This creates the dialog, but it is not displayed. See * C. */ static void create_connection_dialog (struct config *config) { GtkWidget *intro, *table; GtkWidget *server_label; GtkWidget *server_hbox; GtkWidget *port_colon_label; GtkWidget *username_label; GtkWidget *password_label; GtkWidget *identity_label; GtkWidget *test_hbox, *test; GtkWidget *about; GtkWidget *configure_network; GtkWidget *xterm; char port_str[64]; int row; conn_dlg = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (conn_dlg), g_get_prgname ()); gtk_window_set_resizable (GTK_WINDOW (conn_dlg), FALSE); /* The main dialog area. */ intro = gtk_label_new (_("Connect to a virt-v2v conversion server over SSH:")); gtk_label_set_line_wrap (GTK_LABEL (intro), TRUE); set_padding (intro, 10, 10); table_new (table, 5, 2); row = 0; server_label = gtk_label_new_with_mnemonic (_("Conversion _server:")); table_attach (table, server_label, 0, 1, row, GTK_FILL, GTK_FILL, 4, 4); set_alignment (server_label, 1., 0.5); hbox_new (server_hbox, FALSE, 4); server_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (server_label), server_entry); if (config->remote.server != NULL) gtk_entry_set_text (GTK_ENTRY (server_entry), config->remote.server); port_colon_label = gtk_label_new (":"); port_entry = gtk_entry_new (); gtk_entry_set_width_chars (GTK_ENTRY (port_entry), 6); snprintf (port_str, sizeof port_str, "%d", config->remote.port); gtk_entry_set_text (GTK_ENTRY (port_entry), port_str); gtk_box_pack_start (GTK_BOX (server_hbox), server_entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (server_hbox), port_colon_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (server_hbox), port_entry, FALSE, FALSE, 0); table_attach (table, server_hbox, 1, 2, row, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); row++; username_label = gtk_label_new_with_mnemonic (_("_User name:")); table_attach (table, username_label, 0, 1, row, GTK_FILL, GTK_FILL, 4, 4); set_alignment (username_label, 1., 0.5); username_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (username_label), username_entry); if (config->auth.username != NULL) gtk_entry_set_text (GTK_ENTRY (username_entry), config->auth.username); else gtk_entry_set_text (GTK_ENTRY (username_entry), "root"); table_attach (table, username_entry, 1, 2, row, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); row++; password_label = gtk_label_new_with_mnemonic (_("_Password:")); table_attach (table, password_label, 0, 1, row, GTK_FILL, GTK_FILL, 4, 4); set_alignment (password_label, 1., 0.5); password_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (password_label), password_entry); gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE); gtk_entry_set_input_purpose (GTK_ENTRY (password_entry), GTK_INPUT_PURPOSE_PASSWORD); if (config->auth.password != NULL) gtk_entry_set_text (GTK_ENTRY (password_entry), config->auth.password); table_attach (table, password_entry, 1, 2, row, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); row++; identity_label = gtk_label_new_with_mnemonic (_("SSH _Identity URL:")); table_attach (table, identity_label, 0, 1, row, GTK_FILL, GTK_FILL, 4, 4); set_alignment (identity_label, 1., 0.5); identity_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (identity_label), identity_entry); if (config->auth.identity.url != NULL) gtk_entry_set_text (GTK_ENTRY (identity_entry), config->auth.identity.url); table_attach (table, identity_entry, 1, 2, row, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); row++; sudo_button = gtk_check_button_new_with_mnemonic (_("Use su_do when running virt-v2v")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sudo_button), config->auth.sudo); table_attach (table, sudo_button, 1, 2, row, GTK_FILL, GTK_FILL, 4, 4); hbox_new (test_hbox, FALSE, 0); test = gtk_button_new_with_mnemonic (_("_Test connection")); gtk_box_pack_start (GTK_BOX (test_hbox), test, TRUE, FALSE, 0); hbox_new (spinner_hbox, FALSE, 10); spinner = gtk_spinner_new (); gtk_box_pack_start (GTK_BOX (spinner_hbox), spinner, FALSE, FALSE, 0); spinner_message = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (spinner_message), TRUE); set_padding (spinner_message, 10, 10); gtk_box_pack_start (GTK_BOX (spinner_hbox), spinner_message, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), intro, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), table, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), test_hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), spinner_hbox, TRUE, TRUE, 0); /* Buttons. */ gtk_dialog_add_buttons (GTK_DIALOG (conn_dlg), _("_Configure network ..."), 1, _("_XTerm ..."), 2, _("_About virt-p2v " PACKAGE_VERSION " ..."), 3, _("_Next"), 4, NULL); next_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 4); gtk_widget_set_sensitive (next_button, FALSE); configure_network = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 1); xterm = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 2); about = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 3); /* Signals. */ g_signal_connect_swapped (G_OBJECT (conn_dlg), "destroy", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (test), "clicked", G_CALLBACK (test_connection_clicked), config); g_signal_connect (G_OBJECT (configure_network), "clicked", G_CALLBACK (configure_network_button_clicked), NULL); g_signal_connect (G_OBJECT (xterm), "clicked", G_CALLBACK (xterm_button_clicked), NULL); g_signal_connect (G_OBJECT (about), "clicked", G_CALLBACK (about_button_clicked), NULL); g_signal_connect (G_OBJECT (next_button), "clicked", G_CALLBACK (connection_next_clicked), NULL); g_signal_connect (G_OBJECT (username_entry), "changed", G_CALLBACK (username_changed_callback), NULL); g_signal_connect (G_OBJECT (password_entry), "changed", G_CALLBACK (password_or_identity_changed_callback), NULL); g_signal_connect (G_OBJECT (identity_entry), "changed", G_CALLBACK (password_or_identity_changed_callback), NULL); /* Call this signal to initialize the sensitivity of the sudo * button correctly. */ username_changed_callback (NULL, NULL); } /** * If the username is "root", disable the sudo button. */ static void username_changed_callback (GtkWidget *w, gpointer data) { const char *str; int username_is_root; int sudo_is_set; str = gtk_entry_get_text (GTK_ENTRY (username_entry)); username_is_root = str != NULL && STREQ (str, "root"); sudo_is_set = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sudo_button)); /* The sudo button is sensitive if: * - The username is not "root", or * - The button is not already checked (to allow the user to uncheck it) */ gtk_widget_set_sensitive (sudo_button, !username_is_root || sudo_is_set); } /** * The password or SSH identity URL entries are mutually exclusive, so * if one contains text then disable the other. This function is * called when the "changed" signal is received on either. */ static void password_or_identity_changed_callback (GtkWidget *w, gpointer data) { const char *str; int password_set; int identity_set; str = gtk_entry_get_text (GTK_ENTRY (password_entry)); password_set = str != NULL && STRNEQ (str, ""); str = gtk_entry_get_text (GTK_ENTRY (identity_entry)); identity_set = str != NULL && STRNEQ (str, ""); if (!password_set && !identity_set) { gtk_widget_set_sensitive (password_entry, TRUE); gtk_widget_set_sensitive (identity_entry, TRUE); } else if (identity_set) gtk_widget_set_sensitive (password_entry, FALSE); else if (password_set) gtk_widget_set_sensitive (identity_entry, FALSE); } /** * Hide all other dialogs and show the connection dialog. */ static void show_connection_dialog (void) { /* Hide the other dialogs. */ gtk_widget_hide (conv_dlg); gtk_widget_hide (run_dlg); /* Show everything except the spinner. */ gtk_widget_show_all (conn_dlg); gtk_widget_hide (spinner_hbox); } /** * Callback from the C button. * * This initiates a background thread which actually does the ssh to * the conversion server and the rest of the testing (see * C). */ static void test_connection_clicked (GtkWidget *w, gpointer data) { struct config *config = data; const gchar *port_str; const gchar *identity_str; size_t errors = 0; struct config *copy; int err; pthread_t tid; pthread_attr_t attr; gtk_label_set_text (GTK_LABEL (spinner_message), ""); gtk_widget_show_all (spinner_hbox); gtk_widget_hide (spinner); /* Get the fields from the various widgets. */ free (config->remote.server); config->remote.server = strdup (gtk_entry_get_text (GTK_ENTRY (server_entry))); if (STREQ (config->remote.server, "")) { gtk_label_set_text (GTK_LABEL (spinner_message), _("error: No conversion server given.")); gtk_widget_grab_focus (server_entry); errors++; } port_str = gtk_entry_get_text (GTK_ENTRY (port_entry)); if (sscanf (port_str, "%d", &config->remote.port) != 1 || config->remote.port <= 0 || config->remote.port >= 65536) { gtk_label_set_text (GTK_LABEL (spinner_message), _("error: Invalid port number. If in doubt, use \"22\".")); gtk_widget_grab_focus (port_entry); errors++; } free (config->auth.username); config->auth.username = strdup (gtk_entry_get_text (GTK_ENTRY (username_entry))); if (STREQ (config->auth.username, "")) { gtk_label_set_text (GTK_LABEL (spinner_message), _("error: No user name. If in doubt, use \"root\".")); gtk_widget_grab_focus (username_entry); errors++; } free (config->auth.password); config->auth.password = strdup (gtk_entry_get_text (GTK_ENTRY (password_entry))); free (config->auth.identity.url); identity_str = gtk_entry_get_text (GTK_ENTRY (identity_entry)); if (identity_str && STRNEQ (identity_str, "")) config->auth.identity.url = strdup (identity_str); else config->auth.identity.url = NULL; config->auth.identity.file_needs_update = 1; config->auth.sudo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sudo_button)); if (errors) return; /* Give the testing thread its own copy of the config in case we * update the config in the main thread. */ copy = copy_config (config); /* No errors so far, so test the connection in a background thread. */ pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); err = pthread_create (&tid, &attr, test_connection_thread, copy); if (err != 0) error (EXIT_FAILURE, err, "pthread_create"); pthread_attr_destroy (&attr); } /** * Run C (in a detached background thread). Once it * finishes stop the spinner and set the spinner message * appropriately. If the test is successful then we enable the * C button. If unsuccessful, an error is shown in the * connection dialog. */ static void * test_connection_thread (void *data) { struct config *copy = data; int r; g_idle_add (start_spinner, NULL); wait_network_online (copy); r = test_connection (copy); free_config (copy); g_idle_add (stop_spinner, NULL); if (r == -1) g_idle_add (test_connection_error, NULL); else g_idle_add (test_connection_ok, NULL); /* Thread is detached anyway, so no one is waiting for the status. */ return NULL; } /** * Idle task called from C (but run on the * main thread) to start the spinner in the connection dialog. */ static gboolean start_spinner (gpointer user_data) { gtk_label_set_text (GTK_LABEL (spinner_message), _("Testing the connection to the conversion server ...")); gtk_widget_show (spinner); gtk_spinner_start (GTK_SPINNER (spinner)); return FALSE; } /** * Idle task called from C (but run on the * main thread) to stop the spinner in the connection dialog. */ static gboolean stop_spinner (gpointer user_data) { gtk_spinner_stop (GTK_SPINNER (spinner)); gtk_widget_hide (spinner); return FALSE; } /** * Idle task called from C (but run on the * main thread) when there is an error. Display the error message and * disable the C button so the user is forced to correct it. */ static gboolean test_connection_error (gpointer user_data) { const char *err = get_ssh_error (); gtk_label_set_text (GTK_LABEL (spinner_message), err); /* Disable the Next button. */ gtk_widget_set_sensitive (next_button, FALSE); return FALSE; } /** * Idle task called from C (but run on the * main thread) when the connection test was successful. */ static gboolean test_connection_ok (gpointer user_data) { gtk_label_set_text (GTK_LABEL (spinner_message), _("Connected to the conversion server.\n" "Press the \"Next\" button to configure the conversion process.")); /* Enable the Next button. */ gtk_widget_set_sensitive (next_button, TRUE); gtk_widget_grab_focus (next_button); /* Update the information in the conversion dialog. */ set_info_label (); return FALSE; } /** * Callback from the C button. This dialog is * handled entirely by an external program which is part of * NetworkManager. */ static void configure_network_button_clicked (GtkWidget *w, gpointer data) { if (access ("/sbin/yast2", X_OK) >= 0) ignore_value (system ("yast2 lan &")); else ignore_value (system ("nm-connection-editor &")); } /** * Callback from the C button. */ static void xterm_button_clicked (GtkWidget *w, gpointer data) { ignore_value (system ("xterm &")); } /** * Callback from the C button. * * See also F and F. */ static void about_button_clicked (GtkWidget *w, gpointer data) { GtkWidget *dialog; GtkWidget *parent = conn_dlg; dialog = gtk_about_dialog_new (); g_object_set (G_OBJECT (dialog), "program-name", g_get_prgname (), "version", PACKAGE_VERSION_FULL " (" host_cpu ")", "copyright", "\u00A9 2009-2019 Red Hat Inc.", "comments", _("Virtualize a physical machine to run on KVM"), "license-type", GTK_LICENSE_GPL_2_0, "website", "http://libguestfs.org/", "authors", authors, NULL); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } /** * Callback when the connection dialog C button has been * clicked. */ static void connection_next_clicked (GtkWidget *w, gpointer data) { /* Switch to the conversion dialog. */ show_conversion_dialog (); } /*----------------------------------------------------------------------*/ /* Conversion dialog. */ static void populate_disks_store (GtkListStore *disks_store, const char * const *disks); static void populate_disks (GtkTreeView *disks_list_p, const char * const *disks); static void populate_removable_store (GtkListStore *removable_store, const char * const *removable); static void populate_removable (GtkTreeView *removable_list_p, const char * const *removable); static void populate_interfaces (GtkTreeView *interfaces_list_p); static void toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data); static void network_edited_callback (GtkCellRendererToggle *cell, gchar *path_str, gchar *new_text, gpointer data); static gboolean maybe_identify_click (GtkWidget *interfaces_list_p, GdkEventButton *event, gpointer data); static void set_disks_from_ui (struct config *); static void set_removable_from_ui (struct config *); static void set_interfaces_from_ui (struct config *); static void conversion_back_clicked (GtkWidget *w, gpointer data); static void refresh_disks_clicked (GtkWidget *w, gpointer data); static void start_conversion_clicked (GtkWidget *w, gpointer data); static void vcpu_topo_toggled (GtkWidget *w, gpointer data); static void vcpus_or_memory_check_callback (GtkWidget *w, gpointer data); static void notify_ui_callback (int type, const char *data); static bool get_phys_topo_from_conv_dlg (void); static int get_vcpus_from_conv_dlg (void); static uint64_t get_memory_from_conv_dlg (void); enum { DISKS_COL_CONVERT = 0, DISKS_COL_HW_NAME, DISKS_COL_DEVICE, NUM_DISKS_COLS, }; enum { REMOVABLE_COL_CONVERT = 0, REMOVABLE_COL_HW_NAME, REMOVABLE_COL_DEVICE, NUM_REMOVABLE_COLS, }; enum { INTERFACES_COL_CONVERT = 0, INTERFACES_COL_DEVICE, INTERFACES_COL_NETWORK, NUM_INTERFACES_COLS, }; /** * Create the conversion dialog. * * This creates the dialog, but it is not displayed. See * C. */ static void create_conversion_dialog (struct config *config, const char * const *disks, const char * const *removable) { GtkWidget *back, *refresh_disks, *start_button; GtkWidget *hbox, *left_vbox, *right_vbox; GtkWidget *target_frame, *target_vbox, *target_tbl; GtkWidget *guestname_label, *vcpus_label, *memory_label; GtkWidget *output_frame, *output_vbox, *output_tbl; GtkWidget *o_label, *oa_label, *oc_label, *of_label, *os_label; GtkWidget *info_frame; GtkWidget *disks_frame, *disks_sw; GtkWidget *removable_frame, *removable_sw; GtkWidget *interfaces_frame, *interfaces_sw; char vcpus_str[64]; char memory_str[64]; int row; conv_dlg = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (conv_dlg), g_get_prgname ()); gtk_window_set_resizable (GTK_WINDOW (conv_dlg), FALSE); /* XXX It would be nice not to have to set this explicitly, but * if we don't then Gtk chooses a very small window. */ gtk_widget_set_size_request (conv_dlg, 900, 600); /* The main dialog area. */ hbox_new (hbox, TRUE, 1); vbox_new (left_vbox, FALSE, 1); vbox_new (right_vbox, TRUE, 1); /* The left column: target properties and output options. */ target_frame = gtk_frame_new (_("Target properties")); gtk_container_set_border_width (GTK_CONTAINER (target_frame), 4); vbox_new (target_vbox, FALSE, 1); table_new (target_tbl, 4, 3); row = 0; guestname_label = gtk_label_new_with_mnemonic (_("_Name:")); table_attach (target_tbl, guestname_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (guestname_label, 1., 0.5); guestname_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (guestname_label), guestname_entry); if (config->guestname != NULL) gtk_entry_set_text (GTK_ENTRY (guestname_entry), config->guestname); table_attach (target_tbl, guestname_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; vcpu_topo = gtk_check_button_new_with_mnemonic ( _("Copy fully populated _pCPU topology")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vcpu_topo), config->vcpu.phys_topo); table_attach (target_tbl, vcpu_topo, 0, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; vcpus_label = gtk_label_new_with_mnemonic (_("# _vCPUs:")); table_attach (target_tbl, vcpus_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (vcpus_label, 1., 0.5); vcpus_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (vcpus_label), vcpus_entry); snprintf (vcpus_str, sizeof vcpus_str, "%d", config->vcpu.cores); gtk_entry_set_text (GTK_ENTRY (vcpus_entry), vcpus_str); vcpus_entry_when_last_sensitive = config->vcpu.cores; table_attach (target_tbl, vcpus_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); vcpus_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON); table_attach (target_tbl, vcpus_warning, 2, 3, row, 0, 0, 1, 1); row++; memory_label = gtk_label_new_with_mnemonic (_("_Memory (MB):")); table_attach (target_tbl, memory_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (memory_label, 1., 0.5); memory_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (memory_label), memory_entry); snprintf (memory_str, sizeof memory_str, "%" PRIu64, config->memory / 1024 / 1024); gtk_entry_set_text (GTK_ENTRY (memory_entry), memory_str); table_attach (target_tbl, memory_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); memory_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON); table_attach (target_tbl, memory_warning, 2, 3, row, 0, 0, 1, 1); gtk_box_pack_start (GTK_BOX (target_vbox), target_tbl, TRUE, TRUE, 0); target_warning_label = gtk_label_new (""); gtk_label_set_line_wrap (GTK_LABEL (target_warning_label), TRUE); gtk_label_set_line_wrap_mode (GTK_LABEL (target_warning_label), PANGO_WRAP_WORD); gtk_label_set_max_width_chars (GTK_LABEL (target_warning_label), 50); gtk_widget_set_size_request (target_warning_label, -1, 7 * 16); gtk_box_pack_end (GTK_BOX (target_vbox), target_warning_label, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (target_frame), target_vbox); output_frame = gtk_frame_new (_("Virt-v2v output options")); gtk_container_set_border_width (GTK_CONTAINER (output_frame), 4); vbox_new (output_vbox, FALSE, 1); table_new (output_tbl, 5, 2); row = 0; o_label = gtk_label_new_with_mnemonic (_("Output _to (-o):")); table_attach (output_tbl, o_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (o_label, 1., 0.5); o_combo = gtk_combo_box_text_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (o_label), o_combo); gtk_widget_set_tooltip_markup (o_combo, _("libvirt means send the converted guest to libvirt-managed KVM on the conversion server. local means put it in a directory on the conversion server. rhv means write it to RHV-M/oVirt. glance means write it to OpenStack Glance. See the virt-v2v(1) manual page for more information about output options.")); repopulate_output_combo (config); table_attach (output_tbl, o_combo, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; oc_label = gtk_label_new_with_mnemonic (_("_Output conn. (-oc):")); table_attach (output_tbl, oc_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (oc_label, 1., 0.5); oc_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (oc_label), oc_entry); gtk_widget_set_tooltip_markup (oc_entry, _("For libvirt only, the libvirt connection URI, or leave blank to add the guest to the default libvirt instance on the conversion server. For others, leave this field blank.")); if (config->output.connection != NULL) gtk_entry_set_text (GTK_ENTRY (oc_entry), config->output.connection); table_attach (output_tbl, oc_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; os_label = gtk_label_new_with_mnemonic (_("Output _storage (-os):")); table_attach (output_tbl, os_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (os_label, 1., 0.5); os_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (os_label), os_entry); gtk_widget_set_tooltip_markup (os_entry, _("For local, put the directory name on the conversion server. For rhv, put the Export Storage Domain (server:/mountpoint). For others, leave this field blank.")); if (config->output.storage != NULL) gtk_entry_set_text (GTK_ENTRY (os_entry), config->output.storage); table_attach (output_tbl, os_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; of_label = gtk_label_new_with_mnemonic (_("Output _format (-of):")); table_attach (output_tbl, of_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (of_label, 1., 0.5); of_entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (of_label), of_entry); gtk_widget_set_tooltip_markup (of_entry, _("The output disk format, typically raw or qcow2. If blank, defaults to raw.")); if (config->output.format != NULL) gtk_entry_set_text (GTK_ENTRY (of_entry), config->output.format); table_attach (output_tbl, of_entry, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); row++; oa_label = gtk_label_new_with_mnemonic (_("Output _allocation (-oa):")); table_attach (output_tbl, oa_label, 0, 1, row, GTK_FILL, GTK_FILL, 1, 1); set_alignment (oa_label, 1., 0.5); oa_combo = gtk_combo_box_text_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (oa_label), oa_combo); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (oa_combo), "sparse"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (oa_combo), "preallocated"); switch (config->output.allocation) { case OUTPUT_ALLOCATION_PREALLOCATED: gtk_combo_box_set_active (GTK_COMBO_BOX (oa_combo), 1); break; default: gtk_combo_box_set_active (GTK_COMBO_BOX (oa_combo), 0); break; } table_attach (output_tbl, oa_combo, 1, 2, row, GTK_FILL, GTK_FILL, 1, 1); gtk_box_pack_start (GTK_BOX (output_vbox), output_tbl, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (output_frame), output_vbox); info_frame = gtk_frame_new (_("Information")); gtk_container_set_border_width (GTK_CONTAINER (info_frame), 4); info_label = gtk_label_new (NULL); set_alignment (info_label, 0.1, 0.5); set_info_label (); gtk_container_add (GTK_CONTAINER (info_frame), info_label); /* The right column: select devices to be converted. */ disks_frame = gtk_frame_new (_("Fixed hard disks")); gtk_container_set_border_width (GTK_CONTAINER (disks_frame), 4); disks_sw = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (disks_sw), 8); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (disks_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); disks_list = gtk_tree_view_new (); populate_disks (GTK_TREE_VIEW (disks_list), disks); scrolled_window_add_with_viewport (disks_sw, disks_list); gtk_container_add (GTK_CONTAINER (disks_frame), disks_sw); removable_frame = gtk_frame_new (_("Removable media")); gtk_container_set_border_width (GTK_CONTAINER (removable_frame), 4); removable_sw = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (removable_sw), 8); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (removable_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); removable_list = gtk_tree_view_new (); populate_removable (GTK_TREE_VIEW (removable_list), removable); scrolled_window_add_with_viewport (removable_sw, removable_list); gtk_container_add (GTK_CONTAINER (removable_frame), removable_sw); interfaces_frame = gtk_frame_new (_("Network interfaces")); gtk_container_set_border_width (GTK_CONTAINER (interfaces_frame), 4); interfaces_sw = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (interfaces_sw), 8); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (interfaces_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); interfaces_list = gtk_tree_view_new (); /* See maybe_identify_click below for what we're doing. */ g_signal_connect (interfaces_list, "button-press-event", G_CALLBACK (maybe_identify_click), NULL); gtk_widget_set_tooltip_markup (interfaces_list, _("Left click on an interface name to flash the light on the physical interface.")); populate_interfaces (GTK_TREE_VIEW (interfaces_list)); scrolled_window_add_with_viewport (interfaces_sw, interfaces_list); gtk_container_add (GTK_CONTAINER (interfaces_frame), interfaces_sw); /* Pack the top level dialog. */ gtk_box_pack_start (GTK_BOX (left_vbox), target_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (left_vbox), output_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (left_vbox), info_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (right_vbox), disks_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (right_vbox), removable_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (right_vbox), interfaces_frame, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), left_vbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), right_vbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conv_dlg))), hbox, TRUE, TRUE, 0); /* Buttons. */ gtk_dialog_add_buttons (GTK_DIALOG (conv_dlg), _("_Back"), 1, _("_Refresh disks (will reset selection)"), 2, _("Start _conversion"), 3, NULL); back = gtk_dialog_get_widget_for_response (GTK_DIALOG (conv_dlg), 1); refresh_disks = gtk_dialog_get_widget_for_response (GTK_DIALOG (conv_dlg), 2); start_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (conv_dlg), 3); /* Disable disk refreshing in case --test-disk was passed. */ if (disks != NULL && disks[0] != NULL && disks[0][0] == '/' && disks[1] == NULL) gtk_widget_set_sensitive (refresh_disks, FALSE); /* Signals. */ g_signal_connect_swapped (G_OBJECT (conv_dlg), "destroy", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (back), "clicked", G_CALLBACK (conversion_back_clicked), NULL); g_signal_connect (G_OBJECT (refresh_disks), "clicked", G_CALLBACK (refresh_disks_clicked), NULL); g_signal_connect (G_OBJECT (start_button), "clicked", G_CALLBACK (start_conversion_clicked), config); g_signal_connect (G_OBJECT (vcpu_topo), "toggled", G_CALLBACK (vcpu_topo_toggled), NULL); g_signal_connect (G_OBJECT (vcpus_entry), "changed", G_CALLBACK (vcpus_or_memory_check_callback), NULL); g_signal_connect (G_OBJECT (memory_entry), "changed", G_CALLBACK (vcpus_or_memory_check_callback), NULL); } /** * Hide all other dialogs and show the conversion dialog. */ static void show_conversion_dialog (void) { /* Hide the other dialogs. */ gtk_widget_hide (conn_dlg); gtk_widget_hide (run_dlg); /* Show the conversion dialog. */ gtk_widget_show_all (conv_dlg); vcpu_topo_toggled (NULL, NULL); vcpus_or_memory_check_callback (NULL, NULL); /* output_drivers may have been updated, so repopulate o_combo. */ repopulate_output_combo (NULL); } /** * Update the C section in the conversion dialog. * * Note that C (the remote virt-v2v version) is read from * the remote virt-v2v in the C function. */ static void set_info_label (void) { CLEANUP_FREE char *text; int r; if (!v2v_version) r = asprintf (&text, _("virt-p2v (client):\n%s"), PACKAGE_VERSION); else r = asprintf (&text, _("virt-p2v (client):\n" "%s\n" "virt-v2v (conversion server):\n" "%s"), PACKAGE_VERSION_FULL, v2v_version); if (r == -1) { perror ("asprintf"); return; } gtk_label_set_text (GTK_LABEL (info_label), text); } /** * Repopulate the list of output drivers in the C * combo. The list of drivers is read from the remote virt-v2v * instance in C. */ static void repopulate_output_combo (struct config *config) { GtkTreeModel *model; CLEANUP_FREE char *output; size_t i; /* Which driver is currently selected? */ if (config && config->output.type) output = strdup (config->output.type); else output = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (o_combo)); /* Remove existing rows in o_combo. */ model = gtk_combo_box_get_model (GTK_COMBO_BOX (o_combo)); gtk_list_store_clear (GTK_LIST_STORE (model)); /* List of output_drivers from virt-v2v not read yet, so present * a standard set of drivers. */ if (output_drivers == NULL) { gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "libvirt"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "local"); /* Use rhev instead of rhv here so we can work with old virt-v2v. */ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "rhev"); if (output == NULL || STREQ (output, "libvirt")) gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 0); else if (STREQ (output, "local")) gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 1); else if (STREQ (output, "rhev")) gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 2); } /* List of -o options read from remote virt-v2v --machine-readable. */ else { for (i = 0; output_drivers[i] != NULL; ++i) gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), output_drivers[i]); if (output) { for (i = 0; output_drivers[i] != NULL; ++i) if (STREQ (output, output_drivers[i])) gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), i); } else gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 0); } } /** * Populate the C treeview. */ static void populate_disks_store (GtkListStore *disks_store, const char * const *disks) { size_t i; if (disks == NULL) return; for (i = 0; disks[i] != NULL; ++i) { uint64_t size; CLEANUP_FREE char *size_gb = NULL; CLEANUP_FREE char *model = NULL; CLEANUP_FREE char *serial = NULL; CLEANUP_FREE char *device_descr = NULL; GtkTreeIter iter; if (disks[i][0] != '/') { /* not using --test-disk */ size = get_blockdev_size (disks[i]); if (asprintf (&size_gb, "%" PRIu64 "G", size) == -1) error (EXIT_FAILURE, errno, "asprintf"); model = get_blockdev_model (disks[i]); serial = get_blockdev_serial (disks[i]); } if (asprintf (&device_descr, "%s\n" "" "%s %s\n" "%s%s" "", disks[i], size_gb ? size_gb : "", model ? model : "", serial ? "s/n " : "", serial ? serial : "") == -1) error (EXIT_FAILURE, errno, "asprintf"); gtk_list_store_append (disks_store, &iter); gtk_list_store_set (disks_store, &iter, DISKS_COL_CONVERT, TRUE, DISKS_COL_HW_NAME, disks[i], DISKS_COL_DEVICE, device_descr, -1); } } static void populate_disks (GtkTreeView *disks_list_p, const char * const *disks) { GtkListStore *disks_store; GtkCellRenderer *disks_col_convert, *disks_col_device; disks_store = gtk_list_store_new (NUM_DISKS_COLS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); populate_disks_store (disks_store, disks); gtk_tree_view_set_model (disks_list_p, GTK_TREE_MODEL (disks_store)); gtk_tree_view_set_headers_visible (disks_list_p, TRUE); disks_col_convert = gtk_cell_renderer_toggle_new (); gtk_tree_view_insert_column_with_attributes (disks_list_p, -1, _("Convert"), disks_col_convert, "active", DISKS_COL_CONVERT, NULL); gtk_cell_renderer_set_alignment (disks_col_convert, 0.5, 0.0); disks_col_device = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (disks_list_p, -1, _("Device"), disks_col_device, "markup", DISKS_COL_DEVICE, NULL); gtk_cell_renderer_set_alignment (disks_col_device, 0.0, 0.0); g_signal_connect (disks_col_convert, "toggled", G_CALLBACK (toggled), disks_store); } /** * Populate the C treeview. */ static void populate_removable_store (GtkListStore *removable_store, const char * const *removable) { size_t i; if (removable == NULL) return; for (i = 0; removable[i] != NULL; ++i) { CLEANUP_FREE char *device_descr = NULL; GtkTreeIter iter; if (asprintf (&device_descr, "%s\n", removable[i]) == -1) error (EXIT_FAILURE, errno, "asprintf"); gtk_list_store_append (removable_store, &iter); gtk_list_store_set (removable_store, &iter, REMOVABLE_COL_CONVERT, TRUE, REMOVABLE_COL_HW_NAME, removable[i], REMOVABLE_COL_DEVICE, device_descr, -1); } } static void populate_removable (GtkTreeView *removable_list_p, const char * const *removable) { GtkListStore *removable_store; GtkCellRenderer *removable_col_convert, *removable_col_device; removable_store = gtk_list_store_new (NUM_REMOVABLE_COLS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); populate_removable_store (removable_store, removable); gtk_tree_view_set_model (removable_list_p, GTK_TREE_MODEL (removable_store)); gtk_tree_view_set_headers_visible (removable_list_p, TRUE); removable_col_convert = gtk_cell_renderer_toggle_new (); gtk_tree_view_insert_column_with_attributes (removable_list_p, -1, _("Convert"), removable_col_convert, "active", REMOVABLE_COL_CONVERT, NULL); gtk_cell_renderer_set_alignment (removable_col_convert, 0.5, 0.0); removable_col_device = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (removable_list_p, -1, _("Device"), removable_col_device, "markup", REMOVABLE_COL_DEVICE, NULL); gtk_cell_renderer_set_alignment (removable_col_device, 0.0, 0.0); g_signal_connect (removable_col_convert, "toggled", G_CALLBACK (toggled), removable_store); } /** * Populate the C treeview. */ static void populate_interfaces (GtkTreeView *interfaces_list_p) { GtkListStore *interfaces_store; GtkCellRenderer *interfaces_col_convert, *interfaces_col_device, *interfaces_col_network; GtkTreeIter iter; size_t i; interfaces_store = gtk_list_store_new (NUM_INTERFACES_COLS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); if (all_interfaces) { for (i = 0; all_interfaces[i] != NULL; ++i) { const char *if_name = all_interfaces[i]; CLEANUP_FREE char *device_descr = NULL; CLEANUP_FREE char *if_addr = get_if_addr (if_name); CLEANUP_FREE char *if_vendor = get_if_vendor (if_name, 40); if (asprintf (&device_descr, "%s\n" "" "%s\n" "%s" "\n" "Identify interface", if_name, if_addr ? : _("Unknown"), if_vendor ? : _("Unknown")) == -1) error (EXIT_FAILURE, errno, "asprintf"); gtk_list_store_append (interfaces_store, &iter); gtk_list_store_set (interfaces_store, &iter, /* Only convert the first interface. As * they are sorted, this is usually the * physical interface. */ INTERFACES_COL_CONVERT, i == 0, INTERFACES_COL_DEVICE, device_descr, INTERFACES_COL_NETWORK, "default", -1); } } gtk_tree_view_set_model (interfaces_list_p, GTK_TREE_MODEL (interfaces_store)); gtk_tree_view_set_headers_visible (interfaces_list_p, TRUE); interfaces_col_convert = gtk_cell_renderer_toggle_new (); gtk_tree_view_insert_column_with_attributes (interfaces_list_p, -1, _("Convert"), interfaces_col_convert, "active", INTERFACES_COL_CONVERT, NULL); gtk_cell_renderer_set_alignment (interfaces_col_convert, 0.5, 0.0); interfaces_col_device = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (interfaces_list_p, -1, _("Device"), interfaces_col_device, "markup", INTERFACES_COL_DEVICE, NULL); gtk_cell_renderer_set_alignment (interfaces_col_device, 0.0, 0.0); interfaces_col_network = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (interfaces_list_p, -1, _("Connect to virtual network"), interfaces_col_network, "text", INTERFACES_COL_NETWORK, NULL); gtk_cell_renderer_set_alignment (interfaces_col_network, 0.0, 0.0); g_signal_connect (interfaces_col_convert, "toggled", G_CALLBACK (toggled), interfaces_store); g_object_set (interfaces_col_network, "editable", TRUE, NULL); g_signal_connect (interfaces_col_network, "edited", G_CALLBACK (network_edited_callback), interfaces_store); } static void toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data) { GtkTreeModel *model = data; GtkTreePath *path = gtk_tree_path_new_from_string (path_str); GtkTreeIter iter; gboolean v; gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, 0 /* CONVERT */, &v, -1); v ^= 1; gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0 /* CONVERT */, v, -1); gtk_tree_path_free (path); } static void network_edited_callback (GtkCellRendererToggle *cell, gchar *path_str, gchar *new_text, gpointer data) { GtkTreeModel *model = data; GtkTreePath *path; GtkTreeIter iter; if (new_text == NULL || STREQ (new_text, "")) return; path = gtk_tree_path_new_from_string (path_str); gtk_tree_model_get_iter (model, &iter, path); gtk_list_store_set (GTK_LIST_STORE (model), &iter, INTERFACES_COL_NETWORK, new_text, -1); gtk_tree_path_free (path); } /** * When the user clicks on the interface name on the list of * interfaces, we want to run C, which usually * makes some lights flash on the physical interface. * * We cannot catch clicks on the cell itself, so we have to go via a * more obscure route. See L and * L */ static gboolean maybe_identify_click (GtkWidget *interfaces_list_p, GdkEventButton *event, gpointer data) { gboolean ret = FALSE; /* Did we handle this event? */ guint button; /* Single left click only. */ if (gdk_event_get_event_type ((const GdkEvent *) event) == GDK_BUTTON_PRESS && gdk_event_get_button ((const GdkEvent *) event, &button) && button == 1) { GtkTreePath *path; GtkTreeViewColumn *column; gdouble event_x, event_y; if (gdk_event_get_coords ((const GdkEvent *) event, &event_x, &event_y) && gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (interfaces_list_p), event_x, event_y, &path, &column, NULL, NULL)) { GList *cols; gint column_index; /* Get column index. */ cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (interfaces_list_p)); column_index = g_list_index (cols, (gpointer) column); g_list_free (cols); if (column_index == INTERFACES_COL_DEVICE) { const gint *indices; gint row_index; const char *if_name; char *cmd; /* Get the row index. */ indices = gtk_tree_path_get_indices (path); row_index = indices[0]; /* And the interface name. */ if_name = all_interfaces[row_index]; /* Issue the ethtool command in the background. */ if (asprintf (&cmd, "ethtool --identify '%s' 10 &", if_name) == -1) error (EXIT_FAILURE, errno, "asprintf"); printf ("%s\n", cmd); ignore_value (system (cmd)); free (cmd); ret = TRUE; /* We handled this event. */ } gtk_tree_path_free (path); } } return ret; } static void set_from_ui_generic (char ***ret, GtkTreeView *list) { GtkTreeModel *model; enum { COUNT, COPY, DONE } mode; guestfs_int_free_string_list (*ret); *ret = NULL; model = gtk_tree_view_get_model (list); for (mode = COUNT; mode != DONE; mode++) { size_t found; gboolean avail; GtkTreeIter iter; found = 0; avail = gtk_tree_model_get_iter_first (model, &iter); while (avail) { gboolean active; gtk_tree_model_get (model, &iter, 0 /* CONVERT */, &active, -1); if (active) { if (mode == COPY) { gchar *hw_name; gtk_tree_model_get (model, &iter, 1 /* HW_NAME */, &hw_name, -1); /* gtk_tree_model_get() outputs a deep copy, so no need for an * strdup() here */ (*ret)[found] = hw_name; } found++; } avail = gtk_tree_model_iter_next (model, &iter); } /* iteration over entries of "model" */ switch (mode) { case COUNT: if (found == 0) return; *ret = malloc ((found + 1) * sizeof (char *)); if (*ret == NULL) error (EXIT_FAILURE, errno, "malloc"); break; case COPY: (*ret)[found] = NULL; break; default: assert (0); } } /* "mode" loop */ } static void set_disks_from_ui (struct config *config) { set_from_ui_generic (&config->disks, GTK_TREE_VIEW (disks_list)); } static void set_removable_from_ui (struct config *config) { set_from_ui_generic (&config->removable, GTK_TREE_VIEW (removable_list)); } static void set_interfaces_from_ui (struct config *config) { GtkTreeModel *model; GtkTreeIter iter; gboolean b, v; size_t i, j; guestfs_int_free_string_list (config->interfaces); if (all_interfaces == NULL) { config->interfaces = NULL; return; } model = gtk_tree_view_get_model (GTK_TREE_VIEW (interfaces_list)); config->interfaces = malloc ((1 + guestfs_int_count_strings (all_interfaces)) * sizeof (char *)); if (config->interfaces == NULL) error (EXIT_FAILURE, errno, "malloc"); i = j = 0; b = gtk_tree_model_get_iter_first (model, &iter); while (b) { gtk_tree_model_get (model, &iter, INTERFACES_COL_CONVERT, &v, -1); if (v) { assert (all_interfaces[i] != NULL); config->interfaces[j++] = strdup (all_interfaces[i]); } b = gtk_tree_model_iter_next (model, &iter); ++i; } config->interfaces[j] = NULL; } static void set_network_map_from_ui (struct config *config) { GtkTreeView *list; GtkTreeModel *model; GtkTreeIter iter; gboolean b; const char *s; size_t i, j; if (all_interfaces == NULL) { guestfs_int_free_string_list (config->network_map); config->network_map = NULL; return; } list = GTK_TREE_VIEW (interfaces_list); model = gtk_tree_view_get_model (list); guestfs_int_free_string_list (config->network_map); config->network_map = malloc ((1 + guestfs_int_count_strings (all_interfaces)) * sizeof (char *)); if (config->network_map == NULL) error (EXIT_FAILURE, errno, "malloc"); i = j = 0; b = gtk_tree_model_get_iter_first (model, &iter); while (b) { gtk_tree_model_get (model, &iter, INTERFACES_COL_NETWORK, &s, -1); if (s) { assert (all_interfaces[i] != NULL); if (asprintf (&config->network_map[j], "%s:%s", all_interfaces[i], s) == -1) error (EXIT_FAILURE, errno, "asprintf"); ++j; } b = gtk_tree_model_iter_next (model, &iter); ++i; } config->network_map[j] = NULL; } /** * The conversion dialog C button has been clicked. */ static void conversion_back_clicked (GtkWidget *w, gpointer data) { /* Switch to the connection dialog. */ show_connection_dialog (); /* Better disable the Next button so the user is forced to * do "Test connection" again. */ gtk_widget_set_sensitive (next_button, FALSE); } static void refresh_disks_clicked (GtkWidget *w, gpointer data) { GtkTreeModel *model; GtkListStore *disks_store, *removable_store; char **disks, **removable; model = gtk_tree_view_get_model (GTK_TREE_VIEW (disks_list)); disks_store = GTK_LIST_STORE (model); model = gtk_tree_view_get_model (GTK_TREE_VIEW (removable_list)); removable_store = GTK_LIST_STORE (model); gtk_list_store_clear (disks_store); gtk_list_store_clear (removable_store); find_all_disks (&disks, &removable); populate_disks_store (disks_store, (const char **)disks); populate_removable_store (removable_store, (const char **)removable); guestfs_int_free_string_list (removable); guestfs_int_free_string_list (disks); } static char *concat_warning (char *warning, const char *fs, ...) __attribute__((format (printf,2,3))); static char * concat_warning (char *warning, const char *fs, ...) { va_list args; char *msg; size_t len, len2; int r; if (warning == NULL) { warning = strdup (""); if (warning == NULL) malloc_fail: error (EXIT_FAILURE, errno, "malloc"); } len = strlen (warning); if (len > 0 && warning[len-1] != '\n' && fs[0] != '\n') { warning = concat_warning (warning, "\n"); len = strlen (warning); } va_start (args, fs); r = vasprintf (&msg, fs, args); va_end (args); if (r == -1) goto malloc_fail; len2 = strlen (msg); warning = realloc (warning, len + len2 + 1); if (warning == NULL) goto malloc_fail; memcpy (&warning[len], msg, len2 + 1); free (msg); return warning; } static void vcpu_topo_toggled (GtkWidget *w, gpointer data) { bool phys_topo; unsigned vcpus; char vcpus_str[64]; phys_topo = get_phys_topo_from_conv_dlg (); if (phys_topo) { struct cpu_topo topo; get_cpu_topology (&topo); vcpus = topo.sockets * topo.cores * topo.threads; vcpus_entry_when_last_sensitive = get_vcpus_from_conv_dlg (); } else vcpus = vcpus_entry_when_last_sensitive; snprintf (vcpus_str, sizeof vcpus_str, "%u", vcpus); gtk_entry_set_text (GTK_ENTRY (vcpus_entry), vcpus_str); gtk_widget_set_sensitive (vcpus_entry, !phys_topo); } /** * Display a warning if the vCPUs or memory is outside the supported * range (L). */ static void vcpus_or_memory_check_callback (GtkWidget *w, gpointer data) { int vcpus; uint64_t memory; CLEANUP_FREE char *warning = NULL; vcpus = get_vcpus_from_conv_dlg (); memory = get_memory_from_conv_dlg (); if (vcpus > MAX_SUPPORTED_VCPUS) { gtk_widget_show (vcpus_warning); warning = concat_warning (warning, _("Number of virtual CPUs is larger than what is supported for KVM (max: %d)."), MAX_SUPPORTED_VCPUS); } else gtk_widget_hide (vcpus_warning); if (memory > MAX_SUPPORTED_MEMORY_MB * 1024 * 1024) { gtk_widget_show (memory_warning); warning = concat_warning (warning, _("Memory size is larger than what is supported for KVM (max: %" PRIu64 ")."), MAX_SUPPORTED_MEMORY_MB); } else gtk_widget_hide (memory_warning); if (warning != NULL) { warning = concat_warning (warning, _("If you ignore this warning, conversion can still succeed, but the guest may not work or may not be supported on the target.")); gtk_label_set_text (GTK_LABEL (target_warning_label), warning); } else gtk_label_set_text (GTK_LABEL (target_warning_label), ""); } static bool get_phys_topo_from_conv_dlg (void) { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (vcpu_topo)); } static int get_vcpus_from_conv_dlg (void) { const char *str; int i; str = gtk_entry_get_text (GTK_ENTRY (vcpus_entry)); if (sscanf (str, "%d", &i) == 1 && i > 0) return i; else return 1; } static uint64_t get_memory_from_conv_dlg (void) { const char *str; uint64_t i; str = gtk_entry_get_text (GTK_ENTRY (memory_entry)); if (sscanf (str, "%" SCNu64, &i) == 1 && i >= 256) return i * 1024 * 1024; else return UINT64_C (1024) * 1024 * 1024; } /*----------------------------------------------------------------------*/ /* Running dialog. */ static gboolean set_log_dir (gpointer remote_dir); static gboolean set_status (gpointer msg); static gboolean add_v2v_output (gpointer msg); static void *start_conversion_thread (void *data); static gboolean conversion_error (gpointer user_data); static gboolean conversion_finished (gpointer user_data); static void cancel_conversion_dialog (GtkWidget *w, gpointer data); static void activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data); static void shutdown_clicked (GtkWidget *w, gpointer data); static void reboot_clicked (GtkWidget *w, gpointer data); static gboolean close_running_dialog (GtkWidget *w, GdkEvent *event, gpointer data); static const GActionEntry shutdown_actions[] = { { .name = "shutdown", .activate = activate_action }, { .name = "reboot", .activate = activate_action }, }; /** * Create the running dialog. * * This creates the dialog, but it is not displayed. See * C. */ static void create_running_dialog (void) { size_t i; static const char *tags[16] = { "black", "maroon", "green", "olive", "navy", "purple", "teal", "silver", "gray", "red", "lime", "yellow", "blue", "fuchsia", "cyan", "white" }; GtkTextBuffer *buf; GMenu *shutdown_menu; GSimpleActionGroup *shutdown_group; run_dlg = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (run_dlg), g_get_prgname ()); gtk_window_set_resizable (GTK_WINDOW (run_dlg), FALSE); /* The main dialog area. */ v2v_output_sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (v2v_output_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_widget_set_size_request (v2v_output_sw, 700, 400); v2v_output = gtk_text_view_new (); gtk_text_view_set_editable (GTK_TEXT_VIEW (v2v_output), FALSE); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (v2v_output), GTK_WRAP_CHAR); buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (v2v_output)); for (i = 0; i < 16; ++i) { CLEANUP_FREE char *tag_name; if (asprintf (&tag_name, "tag_%s", tags[i]) == -1) error (EXIT_FAILURE, errno, "asprintf"); v2v_output_tags[i] = gtk_text_buffer_create_tag (buf, tag_name, "foreground", tags[i], NULL); } /* XXX This only sets the "CSS" style. It's not clear how to set * the particular font. However (by accident) this does at least * set the widget to use a monospace font. */ GtkStyleContext *context = gtk_widget_get_style_context (v2v_output); gtk_style_context_add_class (context, "monospace"); log_label = gtk_label_new (NULL); set_alignment (log_label, 0., 0.5); set_padding (log_label, 10, 10); set_log_dir (NULL); status_label = gtk_label_new (NULL); set_alignment (status_label, 0., 0.5); set_padding (status_label, 10, 10); gtk_container_add (GTK_CONTAINER (v2v_output_sw), v2v_output); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), v2v_output_sw, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), log_label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), status_label, TRUE, TRUE, 0); /* Shutdown popup menu. */ shutdown_menu = g_menu_new (); g_menu_append (shutdown_menu, _("_Shutdown"), "shutdown.shutdown"); g_menu_append (shutdown_menu, _("_Reboot"), "shutdown.reboot"); shutdown_group = g_simple_action_group_new (); g_action_map_add_action_entries (G_ACTION_MAP (shutdown_group), shutdown_actions, G_N_ELEMENTS (shutdown_actions), NULL); /* Buttons. */ gtk_dialog_add_buttons (GTK_DIALOG (run_dlg), _("_Cancel conversion ..."), 1, NULL); cancel_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (run_dlg), 1); gtk_widget_set_sensitive (cancel_button, FALSE); shutdown_button = gtk_menu_button_new (); gtk_button_set_use_underline (GTK_BUTTON (shutdown_button), TRUE); gtk_button_set_label (GTK_BUTTON (shutdown_button), _("_Shutdown ...")); gtk_button_set_always_show_image (GTK_BUTTON (shutdown_button), TRUE); gtk_widget_insert_action_group (shutdown_button, "shutdown", G_ACTION_GROUP (shutdown_group)); gtk_menu_button_set_use_popover (GTK_MENU_BUTTON (shutdown_button), TRUE); gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (shutdown_button), G_MENU_MODEL (shutdown_menu)); gtk_widget_set_sensitive (shutdown_button, FALSE); gtk_dialog_add_action_widget (GTK_DIALOG (run_dlg), shutdown_button, 2); /* Signals. */ g_signal_connect_swapped (G_OBJECT (run_dlg), "delete_event", G_CALLBACK (close_running_dialog), NULL); g_signal_connect_swapped (G_OBJECT (run_dlg), "destroy", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (cancel_button), "clicked", G_CALLBACK (cancel_conversion_dialog), NULL); } /** * Hide all other dialogs and show the running dialog. */ static void show_running_dialog (void) { /* Hide the other dialogs. */ gtk_widget_hide (conn_dlg); gtk_widget_hide (conv_dlg); /* Show the running dialog. */ gtk_widget_show_all (run_dlg); gtk_widget_set_sensitive (cancel_button, TRUE); if (is_iso_environment) gtk_widget_set_sensitive (shutdown_button, FALSE); } /** * Display the remote log directory in the running dialog. * * If this isn't called from the main thread, then you must only * call it via an idle task (C). * * B This frees the remote_dir (C pointer) which was * strdup'd in C. */ static gboolean set_log_dir (gpointer user_data) { CLEANUP_FREE const char *remote_dir = user_data; CLEANUP_FREE char *msg; if (asprintf (&msg, _("Debug information and log files " "are saved to this directory " "on the conversion server:\n" "%s"), remote_dir ? remote_dir : "") == -1) error (EXIT_FAILURE, errno, "asprintf"); gtk_label_set_text (GTK_LABEL (log_label), msg); return FALSE; } /** * Display the conversion status in the running dialog. * * If this isn't called from the main thread, then you must only * call it via an idle task (C). * * B This frees the message (C pointer) which was * strdup'd in C. */ static gboolean set_status (gpointer user_data) { CLEANUP_FREE const char *msg = user_data; gtk_label_set_text (GTK_LABEL (status_label), msg); return FALSE; } /** * Append output from the virt-v2v process to the buffer, and scroll * to ensure it is visible. * * This function is able to parse ANSI colour sequences and more. * * If this isn't called from the main thread, then you must only * call it via an idle task (C). * * B This frees the message (C pointer) which was * strdup'd in C. */ static gboolean add_v2v_output (gpointer user_data) { CLEANUP_FREE const char *msg = user_data; const char *p; static enum { state_normal, state_escape1, /* seen ESC, expecting [ */ state_escape2, /* seen ESC [, expecting 0 or 1 */ state_escape3, /* seen ESC [ 0/1, expecting ; or m */ state_escape4, /* seen ESC [ 0/1 ;, expecting 3 */ state_escape5, /* seen ESC [ 0/1 ; 3, expecting 1/2/4/5 */ state_escape6, /* seen ESC [ 0/1 ; 3 1/2/5/5, expecting m */ state_cr, /* seen CR */ } state = state_normal; static int colour = 0; static GtkTextTag *tag = NULL; GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (v2v_output)); GtkTextIter iter, iter2; for (p = msg; *p != '\0'; ++p) { char c = *p; switch (state) { case state_normal: if (c == '\r') /* Start of possible CRLF sequence. */ state = state_cr; else if (c == '\x1b') { /* Start of an escape sequence. */ state = state_escape1; colour = 0; } else { /* Treat everything else as a normal char. */ gtk_text_buffer_get_end_iter (buf, &iter); gtk_text_buffer_insert_with_tags (buf, &iter, &c, 1, tag, NULL); } break; case state_escape1: if (c == '[') state = state_escape2; else state = state_normal; break; case state_escape2: if (c == '0') state = state_escape3; else if (c == '1') { state = state_escape3; colour += 8; } else state = state_normal; break; case state_escape3: if (c == ';') state = state_escape4; else if (c == 'm') { tag = NULL; /* restore text colour */ state = state_normal; } else state = state_normal; break; case state_escape4: if (c == '3') state = state_escape5; else state = state_normal; break; case state_escape5: if (c >= '0' && c <= '7') { state = state_escape6; colour += c - '0'; } else state = state_normal; break; case state_escape6: if (c == 'm') { assert (colour >= 0 && colour <= 15); tag = v2v_output_tags[colour]; /* set colour tag */ } state = state_normal; break; case state_cr: if (c == '\n') /* Process CRLF as single a newline character. */ p--; else { /* Delete current (== last) line. */ gtk_text_buffer_get_end_iter (buf, &iter); iter2 = iter; gtk_text_iter_set_line_offset (&iter, 0); /* Delete from iter..iter2 */ gtk_text_buffer_delete (buf, &iter, &iter2); } state = state_normal; break; } /* switch (state) */ } /* for */ /* Scroll to the end of the buffer. */ gtk_text_buffer_get_end_iter (buf, &iter); gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (v2v_output), &iter, 0, FALSE, 0., 1.); return FALSE; } /** * Callback when the C button is clicked. */ static void start_conversion_clicked (GtkWidget *w, gpointer data) { struct config *config = data; const char *str; char *str2; GtkWidget *dlg; struct config *copy; int err; pthread_t tid; pthread_attr_t attr; /* Unpack dialog fields and check them. */ free (config->guestname); config->guestname = strdup (gtk_entry_get_text (GTK_ENTRY (guestname_entry))); if (STREQ (config->guestname, "")) { dlg = gtk_message_dialog_new (GTK_WINDOW (conv_dlg), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("The guest \"Name\" field is empty.")); gtk_window_set_title (GTK_WINDOW (dlg), _("Error")); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); gtk_widget_grab_focus (guestname_entry); return; } config->vcpu.phys_topo = get_phys_topo_from_conv_dlg (); config->vcpu.cores = get_vcpus_from_conv_dlg (); config->memory = get_memory_from_conv_dlg (); /* Get the list of disks to be converted. */ set_disks_from_ui (config); /* The list of disks must be non-empty. */ if (config->disks == NULL || guestfs_int_count_strings (config->disks) == 0) { dlg = gtk_message_dialog_new (GTK_WINDOW (conv_dlg), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("No disks were selected for conversion.\n" "At least one fixed hard disk must be selected.\n")); gtk_window_set_title (GTK_WINDOW (dlg), _("Error")); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); return; } /* List of removable media and network interfaces. */ set_removable_from_ui (config); set_interfaces_from_ui (config); set_network_map_from_ui (config); /* Output selection. */ free (config->output.type); config->output.type = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (o_combo)); config->output.allocation = OUTPUT_ALLOCATION_NONE; str2 = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (oa_combo)); if (str2) { if (STREQ (str2, "sparse")) config->output.allocation = OUTPUT_ALLOCATION_SPARSE; else if (STREQ (str2, "preallocated")) config->output.allocation = OUTPUT_ALLOCATION_PREALLOCATED; free (str2); } free (config->output.connection); str = gtk_entry_get_text (GTK_ENTRY (oc_entry)); if (str && STRNEQ (str, "")) config->output.connection = strdup (str); else config->output.connection = NULL; free (config->output.format); str = gtk_entry_get_text (GTK_ENTRY (of_entry)); if (str && STRNEQ (str, "")) config->output.format = strdup (str); else config->output.format = NULL; free (config->output.storage); str = gtk_entry_get_text (GTK_ENTRY (os_entry)); if (str && STRNEQ (str, "")) config->output.storage = strdup (str); else config->output.storage = NULL; /* Display the UI for conversion. */ show_running_dialog (); /* Do the conversion, in a background thread. */ /* Give the conversion (background) thread its own copy of the * config in case we update the config in the main thread. */ copy = copy_config (config); pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); err = pthread_create (&tid, &attr, start_conversion_thread, copy); if (err != 0) error (EXIT_FAILURE, err, "pthread_create"); pthread_attr_destroy (&attr); } /** * This is the background thread which performs the conversion. */ static void * start_conversion_thread (void *data) { struct config *copy = data; int r; r = start_conversion (copy, notify_ui_callback); free_config (copy); if (r == -1) g_idle_add (conversion_error, NULL); else g_idle_add (conversion_finished, NULL); /* Thread is detached anyway, so no one is waiting for the status. */ return NULL; } /** * Idle task called from C (but run on the * main thread) when there was an error during the conversion. */ static gboolean conversion_error (gpointer user_data) { const char *err = get_conversion_error (); GtkWidget *dlg; dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Conversion failed: %s"), err); gtk_window_set_title (GTK_WINDOW (dlg), _("Conversion failed")); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); /* Disable the cancel button. */ gtk_widget_set_sensitive (cancel_button, FALSE); /* Enable the shutdown button. */ if (is_iso_environment) gtk_widget_set_sensitive (shutdown_button, TRUE); return FALSE; } /** * Idle task called from C (but run on the * main thread) when the conversion completed without errors. */ static gboolean conversion_finished (gpointer user_data) { GtkWidget *dlg; dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, _("The conversion was successful.")); gtk_window_set_title (GTK_WINDOW (dlg), _("Conversion was successful")); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); /* Disable the cancel button. */ gtk_widget_set_sensitive (cancel_button, FALSE); /* Enable the shutdown button. */ if (is_iso_environment) gtk_widget_set_sensitive (shutdown_button, TRUE); return FALSE; } /** * This is called from F:C * when there is a status change or a log message. */ static void notify_ui_callback (int type, const char *data) { /* Because we call the functions as idle callbacks which run * in the main thread some time later, we must duplicate the * 'data' parameter (which is always a \0-terminated string). * * This is freed by the idle task function. */ char *copy = strdup (data); switch (type) { case NOTIFY_LOG_DIR: g_idle_add (set_log_dir, (gpointer) copy); break; case NOTIFY_REMOTE_MESSAGE: g_idle_add (add_v2v_output, (gpointer) copy); break; case NOTIFY_STATUS: g_idle_add (set_status, (gpointer) copy); break; default: fprintf (stderr, "%s: unknown message during conversion: type=%d data=%s\n", g_get_prgname (), type, data); free (copy); } } static gboolean close_running_dialog (GtkWidget *w, GdkEvent *event, gpointer data) { /* This function is called if the user tries to close the running * dialog. This is the same as cancelling the conversion. */ if (conversion_is_running ()) { cancel_conversion (); return TRUE; } else /* Conversion is not running, so this will delete the dialog. */ return FALSE; } /** * This is called when the user clicks on the "Cancel conversion" * button. Since conversions can run for a long time, and cancelling * the conversion is non-recoverable, this function displays a * confirmation dialog before cancelling the conversion. */ static void cancel_conversion_dialog (GtkWidget *w, gpointer data) { GtkWidget *dlg; if (!conversion_is_running ()) return; dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("Really cancel the conversion? " "To convert this machine you will need to " "re-run the conversion from the beginning.")); gtk_window_set_title (GTK_WINDOW (dlg), _("Cancel the conversion")); if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES) /* This makes start_conversion return an error (eventually). */ cancel_conversion (); gtk_widget_destroy (dlg); } static void activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { const char *action_name = g_action_get_name (G_ACTION (action)); if (STREQ (action_name, "shutdown")) shutdown_clicked (NULL, user_data); else if (STREQ (action_name, "reboot")) reboot_clicked (NULL, user_data); } static void shutdown_clicked (GtkWidget *w, gpointer data) { if (!is_iso_environment) return; sync (); sleep (2); ignore_value (system ("/sbin/poweroff")); } static void reboot_clicked (GtkWidget *w, gpointer data) { if (!is_iso_environment) return; sync (); sleep (2); ignore_value (system ("/sbin/reboot")); } virt-p2v-1.42.3/PaxHeaders/Makefile.am0000644000000000000000000000013214321226753014411 xustar0030 mtime=1665478123.018444287 30 atime=1665478123.021444269 30 ctime=1665495228.388332917 virt-p2v-1.42.3/Makefile.am0000644000175000017500000003067014321226753016223 0ustar00rjonesrjones00000000000000# libguestfs virt-p2v # Copyright (C) 2009-2019 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . include $(top_srcdir)/subdir-rules.mk ACLOCAL_AMFLAGS = -I m4 SUBDIRS = gnulib/lib SUBDIRS += docs # bash-completion SUBDIRS += bash EXTRA_DIST = \ $(BUILT_SOURCES) \ $(TESTS) $(LIBGUESTFS_TESTS) $(SLOW_TESTS) \ .gitignore \ AUTHORS \ dependencies.m4 \ generate-p2v-authors.pl \ generate-p2v-config.pl \ issue \ kiwi-config.sh \ kiwi-config.xml.in \ launch-virt-p2v \ libguestfs/README \ make-physical-machine.sh \ miniexpect/README \ p2v.ks.in \ p2v.service \ podcheck.pl \ test-functions.sh \ test-virt-p2v-docs.sh \ test-virt-p2v-pxe.sshd_config.in \ test-virt-p2v-scp.sh \ test-virt-p2v-ssh.sh \ valgrind-suppressions \ virt-p2v.pod \ virt-p2v-make-disk.in \ virt-p2v-make-disk.pod \ virt-p2v-make-kickstart.in \ virt-p2v-make-kickstart.pod \ virt-p2v-make-kiwi.in \ virt-p2v-make-kiwi.pod # Don't clean ssh_host_rsa_key{,.pub} or id_rsa{,.pub} since those # consume system entropy to regenerate. CLEANFILES += \ $(dependencies_files) \ $(generated_sources) \ $(PHYSICAL_MACHINE) $(BLANK_DISK) \ about-authors.c \ physical-machine.tmp.* \ stamp-test-virt-p2v-pxe-data-files \ stamp-test-virt-p2v-pxe-kernel \ test-virt-p2v-pxe.authorized_keys \ test-virt-p2v-pxe.img \ test-virt-p2v-pxe.vmlinuz \ test-virt-p2v-pxe.initramfs \ test-virt-p2v-pxe.sshd_config \ virt-p2v.img \ virt-p2v-kernel-config.pod \ virt-p2v.xz \ website/*.html # Although virt-p2v is a regular binary, it is not usually installed # in /usr/bin since it only functions when contained in an ISO or PXE # image which is used to boot the physical machine (since otherwise # virt-p2v would not be able to get a consistent snapshot of the # physical disks). Also we don't want the naked binary to appear on # the host, which would cause various Gtk dependencies to be pulled # in, so it must be compressed. virtp2vlibdir = $(libdir)/virt-p2v virtp2vlib_DATA = virt-p2v.xz virt-p2v.xz: virt-p2v rm -f $@ $@-t xz --best --keep --stdout $< > $@-t mv $@-t $@ noinst_PROGRAMS = virt-p2v virt_p2v_SOURCES = \ miniexpect/miniexpect.c \ miniexpect/miniexpect.h \ libguestfs/cleanups.c \ libguestfs/cleanups.h \ libguestfs/guestfs-utils.c \ libguestfs/guestfs-utils.h \ libguestfs/libxml2-cleanups.c \ libguestfs/libxml2-writer-macros.h \ conversion.c \ cpuid.c \ disks.c \ gui.c \ gui-gtk3-compat.h \ inhibit.c \ kernel.c \ kernel-cmdline.c \ main.c \ nbd.c \ p2v.h \ p2v-config.h \ physical-xml.c \ rtc.c \ ssh.c \ utils.c generated_sources = \ config.c \ kernel-config.c \ p2v-config.h nodist_virt_p2v_SOURCES = \ $(generated_sources) \ about-authors.c virt_p2v_CPPFLAGS = \ -DLOCALEBASEDIR=\""$(datadir)/locale"\" \ -DGTK_DISABLE_DEPRECATED \ -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_56 \ -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_56 \ -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_22 \ -DGDK_VERSION_MAX_ALLOWED=GDK_VERSION_3_22 \ -I$(srcdir)/libguestfs \ -I$(srcdir)/miniexpect \ -I$(srcdir)/gnulib/lib -Ignulib/lib virt_p2v_CFLAGS = \ -pthread \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ $(PCRE2_CFLAGS) \ $(LIBXML2_CFLAGS) \ $(GTK3_CFLAGS) \ $(DBUS_CFLAGS) virt_p2v_LDADD = \ $(PCRE2_LIBS) \ $(LIBXML2_LIBS) \ $(GTK3_LIBS) \ $(DBUS_LIBS) \ gnulib/lib/libgnu.la \ -lm $(generated_sources) virt-p2v-kernel-config.pod: $(srcdir)/generate-p2v-config.pl $(AM_V_GEN)rm -f $@ $@-t && $(PERL) $(<) --file=$@ --output=$@-t && mv $@-t $@ about-authors.c: $(srcdir)/generate-p2v-authors.pl $(srcdir)/AUTHORS $(AM_V_GEN)rm -f $@ $@-t && $(PERL) $(<) $(srcdir)/AUTHORS > $@-t && mv $@-t $@ # Scripts to build the disk image, USB key, or kickstart. bin_SCRIPTS = virt-p2v-make-disk virt-p2v-make-kickstart virt-p2v-make-kiwi dependencies_files = \ dependencies.archlinux \ dependencies.debian \ dependencies.redhat \ dependencies.suse $(dependencies_files): dependencies.m4 config.status define=`echo $@ | $(SED) 's/dependencies.//;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`; \ m4 -D$$define=1 $< > $@-t mv $@-t $@ # Support files needed by the virt-p2v-make-* scripts. virtp2vdatadir = $(datadir)/virt-p2v virtp2vdata_DATA = \ $(dependencies_files) \ issue \ kiwi-config.sh \ kiwi-config.xml.in \ launch-virt-p2v \ p2v.ks.in \ p2v.service # Manual pages and HTML files for the website. man_MANS = \ virt-p2v.1 \ virt-p2v-make-disk.1 \ virt-p2v-make-kickstart.1 \ virt-p2v-make-kiwi.1 noinst_DATA = \ $(top_builddir)/website/virt-p2v.1.html \ $(top_builddir)/website/virt-p2v-make-disk.1.html \ $(top_builddir)/website/virt-p2v-make-kickstart.1.html \ $(top_builddir)/website/virt-p2v-make-kiwi.1.html virt-p2v.1 $(top_builddir)/website/virt-p2v.1.html: stamp-virt-p2v.pod stamp-virt-p2v.pod: virt-p2v.pod virt-p2v-kernel-config.pod $(PODWRAPPER) \ --man virt-p2v.1 \ --html $(top_builddir)/website/virt-p2v.1.html \ --insert virt-p2v-kernel-config.pod:__KERNEL_CONFIG__ \ --license GPLv2+ \ --warning safe \ $< touch $@ virt-p2v-make-disk.1 $(top_builddir)/website/virt-p2v-make-disk.1.html: stamp-virt-p2v-make-disk.pod stamp-virt-p2v-make-disk.pod: virt-p2v-make-disk.pod $(PODWRAPPER) \ --man virt-p2v-make-disk.1 \ --html $(top_builddir)/website/virt-p2v-make-disk.1.html \ --license GPLv2+ \ --warning safe \ $< touch $@ virt-p2v-make-kickstart.1 $(top_builddir)/website/virt-p2v-make-kickstart.1.html: stamp-virt-p2v-make-kickstart.pod stamp-virt-p2v-make-kickstart.pod: virt-p2v-make-kickstart.pod $(PODWRAPPER) \ --man virt-p2v-make-kickstart.1 \ --html $(top_builddir)/website/virt-p2v-make-kickstart.1.html \ --license GPLv2+ \ --warning safe \ $< touch $@ virt-p2v-make-kiwi.1 $(top_builddir)/website/virt-p2v-make-kiwi.1.html: stamp-virt-p2v-make-kiwi.pod stamp-virt-p2v-make-kiwi.pod: virt-p2v-make-kiwi.pod $(PODWRAPPER) \ --man virt-p2v-make-kiwi.1 \ --html $(top_builddir)/website/virt-p2v-make-kiwi.1.html \ --license GPLv2+ \ --warning safe \ $< touch $@ # Run virt-p2v locally either directly or in a VM. # See p2v-hacking(1) section "Running virt-p2v" PHYSICAL_MACHINE = $(abs_builddir)/fedora.img BLANK_DISK = blank-part.img check_DATA = \ $(NULL) if HAVE_LIBGUESTFS check_DATA += \ $(PHYSICAL_MACHINE) \ $(BLANK_DISK) check_SCRIPTS = make-physical-machine.sh endif HAVE_LIBGUESTFS run-virt-p2v-directly: $(PHYSICAL_MACHINE) $(top_builddir)/run virt-p2v --test-disk=$(PHYSICAL_MACHINE) if HAVE_LIBGUESTFS run-virt-p2v-in-a-vm: virt-p2v.img $(PHYSICAL_MACHINE) $(shell guestfish get-hv) \ -M pc,accel=kvm:tcg \ -cpu host \ -smp sockets=1,cores=2,threads=2 \ -m 2048 \ -drive id=hd0,file=$(PHYSICAL_MACHINE),format=raw,if=ide \ -device qemu-xhci \ -drive id=usb0,file=$<,format=raw,snapshot=on,if=none \ -device usb-storage,bootindex=1,drive=usb0 \ -boot menu=on \ -netdev user,id=net0,net=169.254.0.0/16 \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net1 \ -device rtl8139,netdev=net1 \ -netdev user,id=net2 \ -device e1000,netdev=net2 \ $(QEMU_OPTIONS) \ & run-virt-p2v-in-an-nvme-vm: virt-p2v.img $(PHYSICAL_MACHINE) $(BLANK_DISK) $(shell guestfish get-hv) \ -M pc,accel=kvm:tcg \ -cpu host \ -smp sockets=1,cores=2,threads=2 \ -m 2048 \ -boot menu=on \ \ -drive id=phys,if=none,format=raw,file=$(PHYSICAL_MACHINE),snapshot=on \ -device nvme,drive=phys,serial=01234567 \ \ -drive id=usb0,if=none,format=raw,file=$<,snapshot=on \ -device qemu-xhci,id=usb-bus \ -device usb-storage,drive=usb0,bootindex=1,bus=usb-bus.0 \ \ -drive id=blank1,if=none,format=raw,file=$(BLANK_DISK),snapshot=on \ -drive id=blank2,if=none,format=raw,file=$(BLANK_DISK),snapshot=on \ -device nvme,id=nvme-ctrl,serial=89abcdef \ -device nvme-ns,drive=blank1,bus=nvme-ctrl \ -device nvme-ns,drive=blank2,bus=nvme-ctrl \ \ -netdev user,id=net0,net=169.254.0.0/16 \ -device virtio-net-pci,netdev=net0 \ \ -netdev user,id=net1 \ -device rtl8139,netdev=net1 \ \ -netdev user,id=net2 \ -device e1000,netdev=net2 \ \ $(QEMU_OPTIONS) \ & endif HAVE_LIBGUESTFS run-virt-p2v-non-gui-conversion: $(PHYSICAL_MACHINE) stamp-test-virt-p2v-pxe-data-files SLOW=1 $(top_builddir)/run ./test-virt-p2v-pxe.sh $(PHYSICAL_MACHINE): $(top_builddir)/run ./make-physical-machine.sh $@ $(BLANK_DISK): $(top_builddir)/run guestfish -N $@=part exit virt-p2v.img: \ $(dependencies_files) \ issue \ launch-virt-p2v \ p2v.service \ virt-p2v \ virt-p2v-make-disk $(top_builddir)/run virt-p2v-make-disk -o $@ # Tests. TESTS_ENVIRONMENT = $(top_builddir)/run --test TESTS = \ test-virt-p2v-cmdline.sh \ test-virt-p2v-docs.sh LIBGUESTFS_TESTS = \ test-virt-p2v-nbdkit.sh if HAVE_LIBGUESTFS TESTS += \ $(LIBGUESTFS_TESTS) \ $(SLOW_TESTS) endif HAVE_LIBGUESTFS check-valgrind: make VG="@VG@" check SLOW_TESTS = \ test-virt-p2v-pxe.sh check-slow: stamp-test-virt-p2v-pxe-data-files $(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1 stamp-test-virt-p2v-pxe-data-files: \ test-virt-p2v-pxe.authorized_keys \ test-virt-p2v-pxe.img \ test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs \ test-virt-p2v-pxe.sshd_config \ test-virt-p2v-pxe.ssh_host_rsa_key \ test-virt-p2v-pxe.ssh_host_rsa_key.pub \ test-virt-p2v-pxe.id_rsa test-virt-p2v-pxe.id_rsa.pub touch $@ test-virt-p2v-pxe.img: \ $(dependencies_files) \ issue \ launch-virt-p2v \ p2v.service \ test-virt-p2v-pxe.id_rsa \ virt-p2v \ virt-p2v-make-disk $(top_builddir)/run virt-p2v-make-disk \ --inject-ssh-identity=test-virt-p2v-pxe.id_rsa \ -o $@-t mv $@-t $@ test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs: stamp-test-virt-p2v-pxe-kernel stamp-test-virt-p2v-pxe-kernel: test-virt-p2v-pxe.img rm -f $@ vmlinuz initramfs test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs $(top_builddir)/run virt-get-kernel --unversioned-names -a $< mv vmlinuz test-virt-p2v-pxe.vmlinuz mv initramfs test-virt-p2v-pxe.initramfs touch $@ test-virt-p2v-pxe.sshd_config: test-virt-p2v-pxe.sshd_config.in rm -f $@ $@-t @AWK@ \ -v "abs_builddir=$(abs_builddir)" \ '{ \ gsub (/__RANDOM_PORT__/, 10000 + int (1000 * rand())); \ gsub (/__abs_builddir__/, abs_builddir); \ print; \ }' < $< > $@-t chmod 0444 $@-t mv $@-t $@ test-virt-p2v-pxe.authorized_keys: test-virt-p2v-pxe.id_rsa.pub $(top_builddir)/run rm -f $@ $@-t $(top_builddir)/run sh -c 'echo -n environment=\"PATH=$$PATH\"\ ' > $@-t cat $< >> $@-t mv $@-t $@ test-virt-p2v-pxe.ssh_host_rsa_key test-virt-p2v-pxe.ssh_host_rsa_key.pub: stamp-test-virt-p2v-pxe-hostkey stamp-test-virt-p2v-pxe-hostkey: rm -f test-virt-p2v-pxe.ssh_host_rsa_key rm -f test-virt-p2v-pxe.ssh_host_rsa_key.pub ssh-keygen -t rsa -f test-virt-p2v-pxe.ssh_host_rsa_key -N '' touch $@ test-virt-p2v-pxe.id_rsa test-virt-p2v-pxe.id_rsa.pub: stamp-test-virt-p2v-pxe-userkey stamp-test-virt-p2v-pxe-userkey: rm -f test-virt-p2v-pxe.id_rsa rm -f test-virt-p2v-pxe.id_rsa.pub ssh-keygen -t rsa -f test-virt-p2v-pxe.id_rsa -N '' touch $@ # Check no files are missing from EXTRA_DIST rules, and that all # generated files have been included in the tarball. (Note you must # have done 'make dist') maintainer-check-extra-dist: @zcat $(PACKAGE_NAME)-$(VERSION).tar.gz | tar tf - | sort | \ sed 's,^$(PACKAGE_NAME)-$(VERSION)/,,' > tarfiles @git ls-files | \ grep -v \ -e '^\.cirrus.yml' \ -e '^\.gitlab-ci.yml' \ -e '^ci/' | \ sort > gitfiles @comm -13 tarfiles gitfiles > comm-out @echo Checking for differences between EXTRA_DIST and git ... @cat comm-out @[ ! -s comm-out ] @rm tarfiles gitfiles comm-out @echo PASS: EXTRA_DIST tests # Commit everything in current directory to HEAD, and set commit # message to current version (only for maintainer). maintainer-commit: git commit -a -m "Version $(VERSION)." # Tag HEAD with current version (only for maintainer). maintainer-tag: git tag -a "v$(VERSION)" -m "Version $(VERSION)" -f virt-p2v-1.42.3/PaxHeaders/test-functions.sh0000644000000000000000000000013214205675260015700 xustar0030 mtime=1645705904.595187498 30 atime=1665478184.102077916 30 ctime=1665495228.452332508 virt-p2v-1.42.3/test-functions.sh0000755000175000017500000000675314205675260017522 0ustar00rjonesrjones00000000000000#!/bin/bash - # libguestfs # Copyright (C) 2014-2019 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Most of the tests written in shell script source this file for # useful functions. # # To include this file, the test must do: # # $TEST_FUNCTIONS # # (this macro is defined in subdir-rules.mk). # Clean up the environment in every test script. unset CDPATH export LANG=C # When test-functions.sh is invoked, a list of variables is passed as # parameters, so we eval those to define the variables. while [ $# -ge 1 ]; do eval "$1"; shift; done # Skip if $SKIP_ environment variable is set. # Every test should call this function first. skip_if_skipped () { local v if [ -n "$1" ]; then v="SKIP_$(basename $1 | tr a-z.- A-Z__)" else v="SKIP_$(basename $0 | tr a-z.- A-Z__)" fi if [ -n "${!v}" ]; then echo "$(basename $0): test skipped because \$$v is set" exit 77 fi echo "$(basename $0): info: you can skip this test by setting $v=1" } # Skip if the current libguestfs backend is $1. # eg. skip_if_backend uml skip_if_backend () { local b="$(guestfish get-backend)" case "$1" in # Some magic happens for $1 == libvirt. libvirt) if [ "$b" = "libvirt" ] || [[ "$b" =~ ^libvirt: ]]; then echo "$(basename $0): test skipped because the current backend is $b" exit 77 fi ;; *) if [ "$b" = "$1" ]; then echo "$(basename $0): test skipped because the current backend is $b" exit 77 fi ;; esac } # Skip if the current arch != $1. skip_unless_arch () { local m="$(uname -m)" case "$1" in # Some magic happens for some architectures. arm) if [[ ! "$m" =~ ^arm ]]; then echo "$(basename $0): test skipped because the current architecture ($m) is not arm (32 bit)" exit 77 fi ;; i?86) if [[ ! "$m" =~ ^i?86 ]]; then echo "$(basename $0): test skipped because the current architecture ($m) is not $1" exit 77 fi ;; *) if [ "$m" != "$1" ]; then echo "$(basename $0): test skipped because the current architecture ($m) is not $1" exit 77 fi ;; esac } # Run an external command and skip if the command fails. This can be # used to test if a command exists. Normally you should use # `cmd --help' or `cmd --version' or similar. skip_unless () { if ! "$@"; then echo "$(basename $0): test skipped because $1 is not available" exit 77 fi } # Slow tests should always call this function. (See p2v-hacking(1)). slow_test () { if [ -z "$SLOW" ]; then echo "$(basename $0): use 'make check-slow' to run this test" exit 77 fi } virt-p2v-1.42.3/PaxHeaders/valgrind-suppressions0000644000000000000000000000013114321267432016657 xustar0030 mtime=1665494810.686934303 29 atime=1665494822.05086801 30 ctime=1665495228.455332489 virt-p2v-1.42.3/valgrind-suppressions0000644000175000017500000000255314321267432020471 0ustar00rjonesrjones00000000000000# virt-p2v # Copyright (C) 2009-2019 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Valgrind suppressions used when testing only. There are no known # resource leaks in virt-p2v. This file is only for leaks in # libraries that virt-p2v uses. # ld-*.so { ld_leak Memcheck:Leak ... fun:_dl_init } # Gtk { glib_leak_1 Memcheck:Leak ... fun:g_type_register_static } { glib_leak_2 Memcheck:Leak ... fun:g_type_class_ref } { glib_leak_3 Memcheck:Leak ... fun:g_bus_get_sync fun:g_daemon_vfs_init } { atk_leak Memcheck:Leak ... fun:atk_bridge_adaptor_init } # These appeared in glibc 2.35. # See also nbdkit commit f6409b4137c1aeb97d01eef5753f22033d64bfd4 { glibc_leak_4 Memcheck:Leak ... fun:dlopen@@* } virt-p2v-1.42.3/PaxHeaders/COPYING0000644000000000000000000000013214205675260013412 xustar0030 mtime=1645705904.586187587 30 atime=1665494789.828055985 30 ctime=1665495228.417332732 virt-p2v-1.42.3/COPYING0000644000175000017500000004325414205675260015226 0ustar00rjonesrjones00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. virt-p2v-1.42.3/PaxHeaders/physical-xml.c0000644000000000000000000000013214314553633015135 xustar0030 mtime=1664276379.718307614 30 atime=1665478120.032462851 30 ctime=1665495228.435332617 virt-p2v-1.42.3/physical-xml.c0000644000175000017500000002247014314553633016746 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2019 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * Create the F file, which is a piece of phony libvirt * XML used to communicate the metadata of the physical machine to * virt-v2v. */ #include #include #include #include #include #include #include #include #include #include #include "libxml2-writer-macros.h" #include "p2v.h" /* This macro is used by the macros in "libxml2-writer-macros.h" * when an error occurs. */ #define xml_error(fn) \ error (EXIT_FAILURE, errno, \ "%s:%d: error constructing XML near call to \"%s\"", \ __FILE__, __LINE__, (fn)); static const char *map_interface_to_network (struct config *, const char *interface); /** * Write the libvirt XML for this physical machine. * * Note this is not actually input for libvirt. It's input for * virt-v2v on the conversion server. Virt-v2v will (if necessary) * generate the final libvirt XML. */ void generate_physical_xml (struct config *config, struct data_conn *data_conns, const char *filename) { uint64_t memkb; CLEANUP_XMLFREETEXTWRITER xmlTextWriterPtr xo = NULL; size_t i; struct cpu_topo topo; xo = xmlNewTextWriterFilename (filename, 0); if (xo == NULL) error (EXIT_FAILURE, errno, "xmlNewTextWriterFilename"); if (xmlTextWriterSetIndent (xo, 1) == -1 || xmlTextWriterSetIndentString (xo, BAD_CAST " ") == -1) error (EXIT_FAILURE, errno, "could not set XML indent"); if (xmlTextWriterStartDocument (xo, NULL, NULL, NULL) == -1) error (EXIT_FAILURE, errno, "xmlTextWriterStartDocument"); memkb = config->memory / 1024; comment (" %s %s ", g_get_prgname (), PACKAGE_VERSION_FULL); comment (" NOTE!\n" "\n" " This libvirt XML is generated by the virt-p2v front end, in\n" " order to communicate with the backend virt-v2v process running\n" " on the conversion server. It is a minimal description of the\n" " physical machine. If the target of the conversion is libvirt,\n" " then virt-v2v will generate the real target libvirt XML, which\n" " has only a little to do with the XML in this file.\n" "\n" " TL;DR: Don't try to load this XML into libvirt. "); start_element ("domain") { attribute ("type", "physical"); single_element ("name", config->guestname); start_element ("memory") { attribute ("unit", "KiB"); string_format ("%" PRIu64, memkb); } end_element (); start_element ("currentMemory") { attribute ("unit", "KiB"); string_format ("%" PRIu64, memkb); } end_element (); if (config->vcpu.phys_topo) get_cpu_topology (&topo); else { topo.sockets = 1; topo.cores = config->vcpu.cores; topo.threads = 1; } single_element_format ("vcpu", "%u", topo.sockets * topo.cores * topo.threads); /* https://libvirt.org/formatdomain.html#elementsCPU */ start_element ("cpu") { attribute ("match", "minimum"); if (config->cpu.vendor) single_element ("vendor", config->cpu.vendor); if (config->cpu.model) { start_element ("model") { attribute ("fallback", "allow"); string (config->cpu.model); } end_element (); } start_element ("topology") { attribute_format ("sockets", "%u", topo.sockets); attribute_format ("cores", "%u", topo.cores); attribute_format ("threads", "%u", topo.threads); } end_element (); } end_element (); switch (config->rtc.basis) { case BASIS_UNKNOWN: /* Don't emit any element. */ break; case BASIS_UTC: start_element ("clock") { if (config->rtc.offset == 0) attribute ("offset", "utc"); else { attribute ("offset", "variable"); attribute ("basis", "utc"); attribute_format ("adjustment", "%d", config->rtc.offset); } } end_element (); break; case BASIS_LOCALTIME: start_element ("clock") { attribute ("offset", "localtime"); /* config->rtc.offset is always 0 in this case */ } end_element (); break; } start_element ("os") { start_element ("type") { attribute ("arch", host_cpu); string ("hvm"); } end_element (); } end_element (); start_element ("features") { if (config->cpu.acpi) empty_element ("acpi"); if (config->cpu.apic) empty_element ("apic"); if (config->cpu.pae) empty_element ("pae"); } end_element (); start_element ("devices") { for (i = 0; config->disks[i] != NULL; ++i) { char target_dev[64]; if (config->disks[i][0] == '/') { target_sd: memcpy (target_dev, "sd", 2); guestfs_int_drive_name (i, &target_dev[2]); } else { if (strlen (config->disks[i]) <= sizeof (target_dev) - 1) strcpy (target_dev, config->disks[i]); else goto target_sd; } start_element ("disk") { attribute ("type", "network"); attribute ("device", "disk"); start_element ("driver") { attribute ("name", "qemu"); attribute ("type", "raw"); } end_element (); start_element ("source") { attribute ("protocol", "nbd"); start_element ("host") { attribute ("name", "localhost"); attribute_format ("port", "%d", data_conns[i].nbd_remote_port); } end_element (); } end_element (); start_element ("target") { attribute ("dev", target_dev); /* XXX Need to set bus to "ide" or "scsi" here. */ } end_element (); } end_element (); } if (config->removable) { for (i = 0; config->removable[i] != NULL; ++i) { start_element ("disk") { attribute ("type", "network"); attribute ("device", "cdrom"); start_element ("driver") { attribute ("name", "qemu"); attribute ("type", "raw"); } end_element (); start_element ("target") { attribute ("dev", config->removable[i]); } end_element (); } end_element (); } } if (config->interfaces) { for (i = 0; config->interfaces[i] != NULL; ++i) { const char *target_network; CLEANUP_FREE char *mac_filename = NULL; CLEANUP_FREE char *mac = NULL; target_network = map_interface_to_network (config, config->interfaces[i]); if (asprintf (&mac_filename, "/sys/class/net/%s/address", config->interfaces[i]) == -1) error (EXIT_FAILURE, errno, "asprintf"); if (g_file_get_contents (mac_filename, &mac, NULL, NULL)) { const size_t len = strlen (mac); if (len > 0 && mac[len-1] == '\n') mac[len-1] = '\0'; } start_element ("interface") { attribute ("type", "network"); start_element ("source") { attribute ("network", target_network); } end_element (); start_element ("target") { attribute ("dev", config->interfaces[i]); } end_element (); if (mac) { start_element ("mac") { attribute ("address", mac); } end_element (); } } end_element (); } } } end_element (); /* */ } end_element (); /* */ if (xmlTextWriterEndDocument (xo) == -1) error (EXIT_FAILURE, errno, "xmlTextWriterEndDocument"); } /** * Using Cnetwork_map>, map the interface to a target * network name. If no map is found, return C. See * L documentation of C<"p2v.network"> for how the * network map works. * * Note this returns a static string which is only valid as long as * Cnetwork_map> is not freed. */ static const char * map_interface_to_network (struct config *config, const char *interface) { size_t i, len; if (config->network_map == NULL) return "default"; for (i = 0; config->network_map[i] != NULL; ++i) { /* The default map maps everything. */ if (strchr (config->network_map[i], ':') == NULL) return config->network_map[i]; /* interface: ? */ len = strlen (interface); if (STRPREFIX (config->network_map[i], interface) && config->network_map[i][len] == ':') return &config->network_map[i][len+1]; } /* No mapping found. */ return "default"; } virt-p2v-1.42.3/PaxHeaders/main.c0000644000000000000000000000013214314553633013447 xustar0030 mtime=1664276379.718307614 30 atime=1665478120.031462857 30 ctime=1665495228.432332636 virt-p2v-1.42.3/main.c0000644000175000017500000003053514314553633015261 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2019 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* errors in */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" #if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */ #pragma GCC diagnostic ignored "-Wshift-overflow" #endif #include #pragma GCC diagnostic pop #include "ignore-value.h" #include "p2v.h" char **all_interfaces; int is_iso_environment = 0; int feature_colours_option = 0; int force_colour = 0; static void udevadm_settle (void); static void set_config_defaults (struct config *config, const char * const *disks, const char * const *removable); static void find_all_interfaces (void); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char options[] = "Vv"; static const struct option long_options[] = { { "help", 0, 0, HELP_OPTION }, { "cmdline", 1, 0, 0 }, { "color", 0, 0, 0 }, { "colors", 0, 0, 0 }, { "colour", 0, 0, 0 }, { "colours", 0, 0, 0 }, { "iso", 0, 0, 0 }, { "long-options", 0, 0, 0 }, { "short-options", 0, 0, 0 }, { "test-disk", 1, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; static void __attribute__((noreturn)) usage (int status) { if (status != EXIT_SUCCESS) fprintf (stderr, _("Try ‘%s --help’ for more information.\n"), g_get_prgname ()); else { printf (_("%s: Convert a physical machine to use KVM\n" "Copyright (C) 2009-2019 Red Hat Inc.\n" "Usage:\n" " %s [--options]\n" "Options:\n" " --help Display brief help\n" " --cmdline=CMDLINE Used to debug command line parsing\n" " --colors|--colours Use ANSI colour sequences even if not tty\n" " --iso Running in the ISO environment\n" " --test-disk=DISK.IMG For testing, use disk as /dev/sda\n" " -v|--verbose Verbose messages\n" " -V|--version Display version and exit\n" "For more information, see the manpage %s(1).\n"), g_get_prgname (), g_get_prgname (), g_get_prgname ()); } exit (status); } /* XXX Copied from fish/options.c. */ static void display_short_options (const char *format) { while (*format) { if (*format != ':') printf ("-%c\n", *format); ++format; } exit (EXIT_SUCCESS); } static void display_long_options (const struct option *long_options_p) { while (long_options_p->name) { if (STRNEQ (long_options_p->name, "long-options") && STRNEQ (long_options_p->name, "short-options")) printf ("--%s\n", long_options_p->name); long_options_p++; } exit (EXIT_SUCCESS); } 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 (); const char *test_disk = NULL; char **disks, **removable; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); /* We may use random(3) in this program. */ srandom (time (NULL) + getpid ()); /* 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 (); 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 if (STREQ (long_options[option_index].name, "color") || STREQ (long_options[option_index].name, "colour") || STREQ (long_options[option_index].name, "colors") || STREQ (long_options[option_index].name, "colours")) { force_colour = 1; } else if (STREQ (long_options[option_index].name, "iso")) { is_iso_environment = 1; } else if (STREQ (long_options[option_index].name, "test-disk")) { if (test_disk != NULL) error (EXIT_FAILURE, 0, _("only a single --test-disk option can be used")); if (optarg[0] != '/') error (EXIT_FAILURE, 0, _("--test-disk must be an absolute path")); test_disk = optarg; } else error (EXIT_FAILURE, 0, _("unknown long option: %s (%d)"), long_options[option_index].name, option_index); break; case 'v': /* This option does nothing since 1.33.41. Verbose is always * enabled. */ break; case 'V': printf ("%s %s\n", g_get_prgname (), 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"), g_get_prgname ()); usage (EXIT_FAILURE); } test_nbd_server (); /* Find all block devices in the system. */ if (test_disk) { /* For testing and debugging purposes, you can use * --test-disk=/path/to/disk.img */ disks = malloc (2 * sizeof (char *)); if (disks == NULL) error (EXIT_FAILURE, errno, "malloc"); disks[0] = strdup (test_disk); if (disks[0] == NULL) error (EXIT_FAILURE, errno, "strdup"); disks[1] = NULL; removable = NULL; } else find_all_disks (&disks, &removable); set_config_defaults (config, (const char **)disks, (const char **)removable); /* 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->remote.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, (const char **)disks, (const char **)removable); } guestfs_int_free_string_list (cmdline); guestfs_int_free_string_list (removable); guestfs_int_free_string_list (disks); free_config (config); exit (EXIT_SUCCESS); } static void udevadm_settle (void) { ignore_value (system ("udevadm settle")); } static void set_config_defaults (struct config *config, const char * const *disks, const char * const *removable) { long i; char hostname[257]; /* Default guest name is derived from the source hostname. If we * assume that the p2v ISO gets its IP address and hostname from * DHCP, then there is at better than average chance that * gethostname will return the real hostname here. It's better than * trying to fish around in the guest filesystem anyway. */ if (gethostname (hostname, sizeof hostname) == -1) { perror ("gethostname"); /* Generate a simple random name. */ if (guestfs_int_random_string (hostname, 8) == -1) error (EXIT_FAILURE, errno, "guestfs_int_random_string"); } else { char *p; /* If the hostname is an FQDN, truncate before the first dot. */ p = strchr (hostname, '.'); if (p && p > hostname) *p = '\0'; } config->guestname = strdup (hostname); config->vcpu.phys_topo = false; /* Defaults for #vcpus and memory are taken from the physical machine. */ i = sysconf (_SC_NPROCESSORS_ONLN); if (i == -1) { perror ("sysconf: _SC_NPROCESSORS_ONLN"); config->vcpu.cores = 1; } else if (i == 0) config->vcpu.cores = 1; else config->vcpu.cores = i; i = sysconf (_SC_PHYS_PAGES); if (i == -1) { perror ("sysconf: _SC_PHYS_PAGES"); config->memory = 1024 * 1024 * 1024; } else config->memory = i; i = sysconf (_SC_PAGESIZE); if (i == -1) { perror ("sysconf: _SC_PAGESIZE"); config->memory *= 4096; } else config->memory *= i; /* Round up the default memory to a power of 2, since the kernel * memory is not included in the total physical pages returned * above. * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */ config->memory--; config->memory |= config->memory >> 1; config->memory |= config->memory >> 2; config->memory |= config->memory >> 4; config->memory |= config->memory >> 8; config->memory |= config->memory >> 16; config->memory |= config->memory >> 32; config->memory++; get_cpu_config (&config->cpu); get_rtc_config (&config->rtc); if (disks) config->disks = guestfs_int_copy_string_list ((char **)disks); if (removable) config->removable = guestfs_int_copy_string_list ((char **)removable); /* Find all network interfaces in the system. */ find_all_interfaces (); if (all_interfaces) config->interfaces = guestfs_int_copy_string_list (all_interfaces); /* Default output drops the guest onto /var/tmp on the conversion * server, a hopefully safe default. */ config->output.type = strdup ("local"); config->output.storage = strdup ("/var/tmp"); } /** * Enumerate all network interfaces in F and add them * to the global C array. */ static void find_all_interfaces (void) { DIR *dir; struct dirent *d; size_t nr_interfaces = 0; /* The default list of network interfaces is everything in * /sys/class/net which matches some common patterns. */ dir = opendir ("/sys/class/net"); if (!dir) error (EXIT_FAILURE, errno, "opendir: %s", "/sys/class/net"); for (;;) { errno = 0; d = readdir (dir); if (!d) break; /* For systemd predictable names, see: * http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20 * biosdevname is also a possibility here. * Ignore PPP, SLIP, WWAN, bridges, etc. */ if (STRPREFIX (d->d_name, "em") || STRPREFIX (d->d_name, "en") || STRPREFIX (d->d_name, "eth") || STRPREFIX (d->d_name, "wl")) { nr_interfaces++; all_interfaces = realloc (all_interfaces, sizeof (char *) * (nr_interfaces + 1)); if (!all_interfaces) error (EXIT_FAILURE, errno, "realloc"); all_interfaces[nr_interfaces-1] = strdup (d->d_name); all_interfaces[nr_interfaces] = NULL; } } /* Check readdir didn't fail */ if (errno != 0) error (EXIT_FAILURE, errno, "readdir: %s", "/sys/class/net"); /* Close the directory handle */ if (closedir (dir) == -1) error (EXIT_FAILURE, errno, "closedir: %s", "/sys/class/net"); if (all_interfaces) qsort (all_interfaces, nr_interfaces, sizeof (char *), compare_strings); } virt-p2v-1.42.3/PaxHeaders/test-virt-p2v-ssh.sh0000644000000000000000000000013214267535425016162 xustar0030 mtime=1658764053.832410166 30 atime=1665478273.591547235 30 ctime=1665495228.454332496 virt-p2v-1.42.3/test-virt-p2v-ssh.sh0000755000175000017500000000324214267535425017772 0ustar00rjonesrjones00000000000000#!/bin/bash - # Copyright (C) 2014 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # This is an ssh substitute used by test-virt-p2v-nbdkit.sh. TEMP=`getopt \ -o 'l:No:p:R:' \ -- "$@"` if [ $? != 0 ]; then echo "$0: problem parsing the command line arguments" exit 1 fi eval set -- "$TEMP" while true ; do case "$1" in # Regular arguments that we can just ignore. -N) shift ;; -l|-o|-p) shift 2 ;; # ssh -R 0:localhost: (port forwarding). Don't actually # port forward, just return the original port number here so that # the conversion process connects directly to nbdkit. -R) arg="$2" port="$(echo $arg | awk -F: '{print $3}')" echo "Allocated port" $port "for remote forward" shift 2 ;; --) shift break ;; *) echo "$0: internal error ($1)" exit 1 ;; esac done # Now run the interactive shell. exec bash virt-p2v-1.42.3/PaxHeaders/gnulib0000644000000000000000000000013214321270274013555 xustar0030 mtime=1665495228.461332451 30 atime=1665495228.547331902 30 ctime=1665495228.461332451 virt-p2v-1.42.3/gnulib/0000755000175000017500000000000014321270274015436 5ustar00rjonesrjones00000000000000virt-p2v-1.42.3/gnulib/PaxHeaders/lib0000644000000000000000000000013214321270274014323 xustar0030 mtime=1665495228.494332241 30 atime=1665495228.547331902 30 ctime=1665495228.494332241 virt-p2v-1.42.3/gnulib/lib/0000755000175000017500000000000014321270274016204 5ustar00rjonesrjones00000000000000virt-p2v-1.42.3/gnulib/lib/PaxHeaders/ignore-value.h0000644000000000000000000000013214216650430017145 xustar0030 mtime=1648054552.096847323 30 atime=1665478182.916084912 30 ctime=1665495228.492332253 virt-p2v-1.42.3/gnulib/lib/ignore-value.h0000644000175000017500000000423514216650430020755 0ustar00rjonesrjones00000000000000/* ignore a function return without a compiler warning. -*- coding: utf-8 -*- Copyright (C) 2008-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Written by Jim Meyering, Eric Blake and Pádraig Brady. */ /* Use "ignore_value" to avoid a warning when using a function declared with gcc's warn_unused_result attribute, but for which you really do want to ignore the result. Traditionally, people have used a "(void)" cast to indicate that a function's return value is deliberately unused. However, if the function is declared with __attribute__((warn_unused_result)), gcc issues a warning even with the cast. Caution: most of the time, you really should heed gcc's warning, and check the return value. However, in those exceptional cases in which you're sure you know what you're doing, use this function. For the record, here's one of the ignorable warnings: "copy.c:233: warning: ignoring return value of 'fchown', declared with attribute warn_unused_result". */ #ifndef _GL_IGNORE_VALUE_H #define _GL_IGNORE_VALUE_H /* Normally casting an expression to void discards its value, but GCC versions 3.4 and newer have __attribute__ ((__warn_unused_result__)) which may cause unwanted diagnostics in that case. Use __typeof__ and __extension__ to work around the problem, if the workaround is known to be needed. */ #if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) # define ignore_value(x) \ (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) #else # define ignore_value(x) ((void) (x)) #endif #endif virt-p2v-1.42.3/gnulib/lib/PaxHeaders/Makefile.am0000644000000000000000000000013214216650430016433 xustar0030 mtime=1648054552.096847323 30 atime=1665478158.956226255 30 ctime=1665495228.489332272 virt-p2v-1.42.3/gnulib/lib/Makefile.am0000644000175000017500000000216414216650430020242 0ustar00rjonesrjones00000000000000# libguestfs # Copyright (C) 2017-2022 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # This directory contains some dependencies originally from gnulib. # The aim is for everything in this directory to eventually go away. include $(top_srcdir)/subdir-rules.mk noinst_LTLIBRARIES = libgnu.la libgnu_la_SOURCES = \ assure.h \ ignore-value.h \ xstrtol.c \ xstrtol.h \ xstrtoull.c libgnu_la_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ $(GCC_VISIBILITY_HIDDEN) virt-p2v-1.42.3/gnulib/lib/PaxHeaders/assure.h0000644000000000000000000000013214216650430016052 xustar0030 mtime=1648054552.096847323 30 atime=1665478182.621086653 30 ctime=1665495228.491332259 virt-p2v-1.42.3/gnulib/lib/assure.h0000644000175000017500000000226014216650430017656 0ustar00rjonesrjones00000000000000/* Run-time assert-like macros. Copyright (C) 2014-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Written by Paul Eggert. */ #ifndef _GL_ASSURE_H #define _GL_ASSURE_H #include /* Check E's value at runtime, and report an error and abort if not. However, do nothing if NDEBUG is defined. Unlike standard 'assert', this macro always compiles E even when NDEBUG is defined, so as to catch typos and avoid some GCC warnings. */ #ifdef NDEBUG # define assure(E) ((void) (0 && (E))) #else # define assure(E) assert (E) #endif #endif virt-p2v-1.42.3/gnulib/lib/PaxHeaders/xstrtol.h0000644000000000000000000000013214216650430016267 xustar0030 mtime=1648054552.096847323 30 atime=1665478182.614086694 30 ctime=1665495228.493332247 virt-p2v-1.42.3/gnulib/lib/xstrtol.h0000644000175000017500000000330414216650430020073 0ustar00rjonesrjones00000000000000/* A more useful interface to strtol. Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef XSTRTOL_H_ # define XSTRTOL_H_ 1 # include # ifndef _STRTOL_ERROR enum strtol_error { LONGINT_OK = 0, /* These two values can be ORed together, to indicate that both errors occurred. */ LONGINT_OVERFLOW = 1, LONGINT_INVALID_SUFFIX_CHAR = 2, LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW), LONGINT_INVALID = 4 }; typedef enum strtol_error strtol_error; # endif # define _DECLARE_XSTRTOL(name, type) \ strtol_error name (const char *, char **, int, type *, const char *); _DECLARE_XSTRTOL (xstrtol, long int) _DECLARE_XSTRTOL (xstrtoul, unsigned long int) _DECLARE_XSTRTOL (xstrtoimax, intmax_t) _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) #if HAVE_LONG_LONG_INT _DECLARE_XSTRTOL (xstrtoll, long long int) _DECLARE_XSTRTOL (xstrtoull, unsigned long long int) #endif #endif /* not XSTRTOL_H_ */ virt-p2v-1.42.3/gnulib/lib/PaxHeaders/xstrtoull.c0000644000000000000000000000013214216650430016623 xustar0030 mtime=1648054552.096847323 30 atime=1665478182.610086718 30 ctime=1665495228.494332241 virt-p2v-1.42.3/gnulib/lib/xstrtoull.c0000644000175000017500000000026414216650430020431 0ustar00rjonesrjones00000000000000#define __strtol strtoull #define __strtol_t unsigned long long int #define __xstrtol xstrtoull #define STRTOL_T_MINIMUM 0 #define STRTOL_T_MAXIMUM ULLONG_MAX #include "xstrtol.c" virt-p2v-1.42.3/gnulib/lib/PaxHeaders/Makefile.in0000644000000000000000000000013114321227016016440 xustar0029 mtime=1665478158.97922612 30 atime=1665478162.773203738 30 ctime=1665495228.490332266 virt-p2v-1.42.3/gnulib/lib/Makefile.in0000644000175000017500000006032514321227016020253 0ustar00rjonesrjones00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # libguestfs # Copyright (C) 2017-2022 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # This directory contains some dependencies originally from gnulib. # The aim is for everything in this directory to eventually go away. # libguestfs # Copyright (C) 2013 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # subdir-rules.mk should be included in every *subdirectory* Makefile.am. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = gnulib/lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/p2v-progs.m4 $(top_srcdir)/m4/p2v-c.m4 \ $(top_srcdir)/m4/p2v-libraries.m4 \ $(top_srcdir)/m4/p2v-bash-completion.m4 \ $(top_srcdir)/m4/p2v-tests.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libgnu_la_LIBADD = am_libgnu_la_OBJECTS = libgnu_la-xstrtol.lo libgnu_la-xstrtoull.lo libgnu_la_OBJECTS = $(am_libgnu_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libgnu_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libgnu_la-xstrtol.Plo \ ./$(DEPDIR)/libgnu_la-xstrtoull.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnu_la_SOURCES) DIST_SOURCES = $(libgnu_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp $(top_srcdir)/subdir-rules.mk DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BASH_COMPLETIONS_DIR = @BASH_COMPLETIONS_DIR@ BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB2_CFLAGS = @GLIB2_CFLAGS@ GLIB2_LIBS = @GLIB2_LIBS@ GREP = @GREP@ GTK3_CFLAGS = @GTK3_CFLAGS@ GTK3_LIBS = @GTK3_LIBS@ GUESTFISH = @GUESTFISH@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION_FULL = @PACKAGE_VERSION_FULL@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE2_CFLAGS = @PCRE2_CFLAGS@ PCRE2_LIBS = @PCRE2_LIBS@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PODWRAPPER = @PODWRAPPER@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ VIRT_BUILDER = @VIRT_BUILDER@ VIRT_V2V = @VIRT_V2V@ WARN_CFLAGS = @WARN_CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # Editor backup files # Patch original and reject files. # Manual pages - these are all generated from *.pod, so the # pages themselves should all be removed by 'make clean'. # Stamp files used when generating man pages. CLEANFILES = *~ *.bak *.orig *.rej *.1 *.3 *.5 *.8 stamp-*.pod # Files that should be universally removed by 'make distclean'. DISTCLEANFILES = stamp-* # custom silent rules guestfs_am_v_podwrapper = $(guestfs_am_v_podwrapper_@AM_V@) guestfs_am_v_podwrapper_ = $(guestfs_am_v_podwrapper_@AM_DEFAULT_V@) guestfs_am_v_podwrapper_0 = @echo " POD " $@; noinst_LTLIBRARIES = libgnu.la libgnu_la_SOURCES = \ assure.h \ ignore-value.h \ xstrtol.c \ xstrtol.h \ xstrtoull.c libgnu_la_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ $(GCC_VISIBILITY_HIDDEN) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/subdir-rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gnulib/lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign gnulib/lib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_srcdir)/subdir-rules.mk $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnu.la: $(libgnu_la_OBJECTS) $(libgnu_la_DEPENDENCIES) $(EXTRA_libgnu_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnu_la_LINK) $(libgnu_la_OBJECTS) $(libgnu_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnu_la-xstrtol.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnu_la-xstrtoull.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgnu_la-xstrtol.lo: xstrtol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnu_la_CFLAGS) $(CFLAGS) -MT libgnu_la-xstrtol.lo -MD -MP -MF $(DEPDIR)/libgnu_la-xstrtol.Tpo -c -o libgnu_la-xstrtol.lo `test -f 'xstrtol.c' || echo '$(srcdir)/'`xstrtol.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnu_la-xstrtol.Tpo $(DEPDIR)/libgnu_la-xstrtol.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xstrtol.c' object='libgnu_la-xstrtol.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnu_la_CFLAGS) $(CFLAGS) -c -o libgnu_la-xstrtol.lo `test -f 'xstrtol.c' || echo '$(srcdir)/'`xstrtol.c libgnu_la-xstrtoull.lo: xstrtoull.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnu_la_CFLAGS) $(CFLAGS) -MT libgnu_la-xstrtoull.lo -MD -MP -MF $(DEPDIR)/libgnu_la-xstrtoull.Tpo -c -o libgnu_la-xstrtoull.lo `test -f 'xstrtoull.c' || echo '$(srcdir)/'`xstrtoull.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnu_la-xstrtoull.Tpo $(DEPDIR)/libgnu_la-xstrtoull.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xstrtoull.c' object='libgnu_la-xstrtoull.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnu_la_CFLAGS) $(CFLAGS) -c -o libgnu_la-xstrtoull.lo `test -f 'xstrtoull.c' || echo '$(srcdir)/'`xstrtoull.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libgnu_la-xstrtol.Plo -rm -f ./$(DEPDIR)/libgnu_la-xstrtoull.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libgnu_la-xstrtol.Plo -rm -f ./$(DEPDIR)/libgnu_la-xstrtoull.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Test shell scripts should use '$TEST_FUNCTIONS' to get a predefined # set of helper functions for running tests (see # tests/test-functions.sh). # # Notes: # # (1) This is in fact a single command all on one line. The variables # are evaluated in test-functions.sh. # # (2) We use absolute paths here and in test-functions.sh so that the # test can change directory freely. But we also include the # non-absolute values so they can be used by the test script itself. export TEST_FUNCTIONS := \ source $(abs_top_srcdir)/test-functions.sh \ abs_srcdir="$(abs_srcdir)" \ abs_builddir="$(abs_builddir)" \ top_srcdir="$(top_srcdir)" \ top_builddir="$(top_builddir)" \ abs_top_srcdir="$(abs_top_srcdir)" \ abs_top_builddir="$(abs_top_builddir)" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: virt-p2v-1.42.3/gnulib/lib/PaxHeaders/xstrtol.c0000644000000000000000000000013214216650430016262 xustar0030 mtime=1648054552.096847323 30 atime=1665478182.611086712 30 ctime=1665495228.493332247 virt-p2v-1.42.3/gnulib/lib/xstrtol.c0000644000175000017500000001403714216650430020073 0ustar00rjonesrjones00000000000000/* A more useful interface to strtol. Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Written by Jim Meyering. */ #ifndef __strtol # define __strtol strtol # define __strtol_t long int # define __xstrtol xstrtol # define STRTOL_T_MINIMUM LONG_MIN # define STRTOL_T_MAXIMUM LONG_MAX #endif #include #include "xstrtol.h" /* Some pre-ANSI implementations (e.g. SunOS 4) need stderr defined if assertion checking is enabled. */ #include #include #include #include #include #include #include "assure.h" #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) static strtol_error bkm_scale (__strtol_t *x, int scale_factor) { if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor) { *x = STRTOL_T_MINIMUM; return LONGINT_OVERFLOW; } if (STRTOL_T_MAXIMUM / scale_factor < *x) { *x = STRTOL_T_MAXIMUM; return LONGINT_OVERFLOW; } *x *= scale_factor; return LONGINT_OK; } static strtol_error bkm_scale_by_power (__strtol_t *x, int base, int power) { strtol_error err = LONGINT_OK; while (power--) err |= bkm_scale (x, base); return err; } /* FIXME: comment. */ strtol_error __xstrtol (const char *s, char **ptr, int strtol_base, __strtol_t *val, const char *valid_suffixes) { char *t_ptr; char **p; __strtol_t tmp; strtol_error err = LONGINT_OK; assure (0 <= strtol_base && strtol_base <= 36); p = (ptr ? ptr : &t_ptr); errno = 0; if (! TYPE_SIGNED (__strtol_t)) { const char *q = s; unsigned char ch = *q; while (isspace (ch)) ch = *++q; if (ch == '-') return LONGINT_INVALID; } tmp = __strtol (s, p, strtol_base); if (*p == s) { /* If there is no number but there is a valid suffix, assume the number is 1. The string is invalid otherwise. */ if (valid_suffixes && **p && strchr (valid_suffixes, **p)) tmp = 1; else return LONGINT_INVALID; } else if (errno != 0) { if (errno != ERANGE) return LONGINT_INVALID; err = LONGINT_OVERFLOW; } /* Let valid_suffixes == NULL mean "allow any suffix". */ /* FIXME: update all callers except the ones that allow suffixes after the number, changing last parameter NULL to "". */ if (!valid_suffixes) { *val = tmp; return err; } if (**p != '\0') { int base = 1024; int suffixes = 1; strtol_error overflow; if (!strchr (valid_suffixes, **p)) { *val = tmp; return err | LONGINT_INVALID_SUFFIX_CHAR; } switch (**p) { case 'E': case 'G': case 'g': case 'k': case 'K': case 'M': case 'm': case 'P': case 'T': case 't': case 'Y': case 'Z': /* The "valid suffix" '0' is a special flag meaning that an optional second suffix is allowed, which can change the base. A suffix "B" (e.g. "100MB") stands for a power of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for a power of 1024. If no suffix (e.g. "100M"), assume power-of-1024. */ if (strchr (valid_suffixes, '0')) switch (p[0][1]) { case 'i': if (p[0][2] == 'B') suffixes += 2; break; case 'B': case 'D': /* 'D' is obsolescent */ base = 1000; suffixes++; break; } } switch (**p) { case 'b': overflow = bkm_scale (&tmp, 512); break; case 'B': /* This obsolescent first suffix is distinct from the 'B' second suffix above. E.g., 'tar -L 1000B' means change the tape after writing 1000 KiB of data. */ overflow = bkm_scale (&tmp, 1024); break; case 'c': overflow = LONGINT_OK; break; case 'E': /* exa or exbi */ overflow = bkm_scale_by_power (&tmp, base, 6); break; case 'G': /* giga or gibi */ case 'g': /* 'g' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 3); break; case 'k': /* kilo */ case 'K': /* kibi */ overflow = bkm_scale_by_power (&tmp, base, 1); break; case 'M': /* mega or mebi */ case 'm': /* 'm' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 2); break; case 'P': /* peta or pebi */ overflow = bkm_scale_by_power (&tmp, base, 5); break; case 'T': /* tera or tebi */ case 't': /* 't' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 4); break; case 'w': overflow = bkm_scale (&tmp, 2); break; case 'Y': /* yotta or 2**80 */ overflow = bkm_scale_by_power (&tmp, base, 8); break; case 'Z': /* zetta or 2**70 */ overflow = bkm_scale_by_power (&tmp, base, 7); break; default: *val = tmp; return err | LONGINT_INVALID_SUFFIX_CHAR; } err |= overflow; *p += suffixes; if (**p) err |= LONGINT_INVALID_SUFFIX_CHAR; } *val = tmp; return err; } virt-p2v-1.42.3/PaxHeaders/podcheck.pl0000644000000000000000000000013214205675260014474 xustar0030 mtime=1645705904.594187508 30 atime=1665478273.217549542 30 ctime=1665495228.451332514 virt-p2v-1.42.3/podcheck.pl0000755000175000017500000001541014205675260016304 0ustar00rjonesrjones00000000000000#!/usr/bin/env perl # podcheck.pl # Copyright (C) 2016 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . use warnings; use strict; use Pod::Usage; use Getopt::Long; use Pod::Man; =head1 NAME podcheck.pl - Compare man page and tools to check all arguments are documented =head1 SYNOPSIS podcheck.pl virt-foo.pod ./virt-foo [--ignore=--arg,--arg,...] =head1 DESCRIPTION This script compares a manual page (eg. C) and the corresponding tool (eg. C<./virt-foo>) and checks that each command line argument is documented in the manual, and that there is no rogue documentation for arguments which do not exist. It works by running the tool with the standard C<--long-options> and C<--short-options> parameters and comparing their output with the man page. You can also ignore options, in case this script gets things wrong or if there are options that you don't intend to document. =head1 OPTIONS =over 4 =cut my $help; =item B<--help> Display brief help. =cut my $ignore = ""; =item B<--ignore=--arg,--arg,...> Ignore the comma-separated list of arguments given. =cut my @inserts; =item B<--insert filename:__PATTERN__> This works like the L I<--insert> option and should be used where the POD includes patterns which podwrapper would substitute. =cut my @verbatims; =item B<--verbatim filename:__PATTERN__> This works like the podwrapper I<--verbatim> option and should be used where the POD includes patterns which podwrapper would substitute. =cut # Clean up the program name. my $progname = $0; $progname =~ s{.*/}{}; # Parse options. GetOptions ("help|?" => \$help, "ignore=s" => \$ignore, "insert=s" => \@inserts, "verbatim=s" => \@verbatims, ) or pod2usage (2); pod2usage (1) if $help; die "$progname: missing argument: podcheck.pl input.pod tool\n" unless @ARGV == 2; my $input = $ARGV[0]; my $tool = $ARGV[1]; my %ignore = (); $ignore{$_} = 1 foreach (split /,/, $ignore); # Open the man page and slurp it in. my $content = read_whole_file ($input); # Perform @inserts. foreach (@inserts) { my @a = split /:/, $_, 2; die "$progname: $input: no colon in parameter of --insert\n" unless @a >= 2; my $replacement = read_whole_file ($a[0]); my $oldcontent = $content; $content =~ s/$a[1]/$replacement/ge; die "$progname: $input: could not find pattern '$a[1]' in input file\n" if $content eq $oldcontent; } # Perform @verbatims. foreach (@verbatims) { my @a = split /:/, $_, 2; die "$progname: $input: no colon in parameter of --verbatim\n" unless @a >= 2; my $replacement = read_verbatim_file ($a[0]); my $oldcontent = $content; $content =~ s/$a[1]/$replacement/ge; die "$progname: $input: could not find pattern '$a[1]' in input file\n" if $content eq $oldcontent; } # Run the tool with --long-options and --short-options. my @tool_options = (); open PIPE, "$tool --long-options |" or die "$progname: $tool --long-options: $!"; while () { chomp; push @tool_options, $_; } close PIPE; open PIPE, "$tool --short-options |" or die "$progname: $tool --short-options: $!"; while () { chomp; push @tool_options, $_; } close PIPE; my %tool_option_exists = (); $tool_option_exists{$_} = 1 foreach @tool_options; # There are some tool options which we automatically ignore. delete $tool_option_exists{"--color"}; delete $tool_option_exists{"--colour"}; delete $tool_option_exists{"--debug-gc"}; # Run the tool with --help. my $help_content; open PIPE, "LANG=C $tool --help |" or die "$progname: $tool --help: $!"; { local $/ = undef; $help_content = ; } close PIPE; # Do the tests. my $errors = 0; # Check each option exists in the manual. my $tool_options_checked = 0; foreach (sort keys %tool_option_exists) { unless ($ignore{$_}) { $tool_options_checked++; unless ($content =~ /^=item.*B<$_(?:=.*)?>/m) { $errors++; warn "$progname: $input does not define $_\n"; } } } # Check there are no extra options defined in the manual which # don't exist in the tool. my $pod_options_checked = 0; my %pod_options = (); $pod_options{$_} = 1 foreach ( $content =~ /^=item.*B<(-[-\w]+)(?:=.*)?>/gm ); foreach (sort keys %pod_options) { unless ($ignore{$_}) { $pod_options_checked++; unless (exists $tool_option_exists{$_}) { $errors++; warn "$progname: $input defines option $_ which does not exist in the tool\n" } } } # Check the tool's --help output mentions all the options. (For OCaml # tools this is a waste of time since the --help output is generated, # but for C tools it is a genuine test). my $help_options_checked = 0; my %help_options = (); $help_options{$_} = 1 foreach ( $help_content =~ /(? 0; printf "$progname: $tool: checked $tool_options_checked tool options, $pod_options_checked documented options, $help_options_checked help options\n"; exit 0; sub read_whole_file { my $input = shift; local $/ = undef; open FILE, $input or die "$progname: $input: $!"; $_ = ; close FILE; $_; } sub read_verbatim_file { my $input = shift; my $r = ""; open FILE, $input or die "$progname: $input: $!"; while () { $r .= " $_"; } close FILE; $r; } =head1 SEE ALSO L, libguestfs.git/README. =head1 AUTHOR Richard W.M. Jones. =head1 COPYRIGHT Copyright (C) 2016 Red Hat Inc. virt-p2v-1.42.3/PaxHeaders/kernel-cmdline.c0000644000000000000000000000013214205675260015414 xustar0030 mtime=1645705904.591187538 30 atime=1665478182.889085072 30 ctime=1665495228.431332642 virt-p2v-1.42.3/kernel-cmdline.c0000644000175000017500000001115114205675260017217 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2015 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * Mini library to read and parse C. */ #include #include #include #include #include #include #include #include "p2v.h" static void add_null (char ***argv, size_t *lenp) { (*lenp)++; *argv = realloc (*argv, *lenp * sizeof (char *)); if (*argv == NULL) error (EXIT_FAILURE, errno, "realloc"); (*argv)[(*lenp)-1] = NULL; } static void add_string (char ***argv, size_t *lenp, const char *str, size_t len) { add_null (argv, lenp); (*argv)[(*lenp)-1] = strndup (str, len); if ((*argv)[(*lenp)-1] == NULL) error (EXIT_FAILURE, errno, "strndup"); } /** * Read and parse C. * * We only support double quoting, consistent with the Linux * documentation. * L * * systemd supports single and double quoting and single character * escaping, but we don't support all that. * * Returns a list of key, value pairs, terminated by C. */ char ** parse_cmdline_string (const char *cmdline) { char **ret = NULL; size_t len = 0; const char *p, *key = NULL, *value = NULL; enum { KEY_START = 0, KEY, VALUE_START, VALUE, VALUE_QUOTED } state = 0; for (p = cmdline; *p; p++) { switch (state) { case KEY_START: /* looking for the start of a key */ if (*p == ' ') continue; key = p; state = KEY; break; case KEY: /* reading key */ if (*p == ' ') { add_string (&ret, &len, key, p-key); add_string (&ret, &len, "", 0); state = KEY_START; } else if (*p == '=') { add_string (&ret, &len, key, p-key); state = VALUE_START; } break; case VALUE_START: /* looking for the start of a value */ if (*p == ' ') { add_string (&ret, &len, "", 0); state = KEY_START; } else if (*p == '"') { value = p+1; state = VALUE_QUOTED; } else { value = p; state = VALUE; } break; case VALUE: /* reading unquoted value */ if (*p == ' ') { add_string (&ret, &len, value, p-value); state = KEY_START; } break; case VALUE_QUOTED: /* reading quoted value */ if (*p == '"') { add_string (&ret, &len, value, p-value); state = KEY_START; } break; } } switch (state) { case KEY_START: break; case KEY: /* key followed by end of string */ add_string (&ret, &len, key, p-key); add_string (&ret, &len, "", 0); break; case VALUE_START: /* key= followed by end of string */ add_string (&ret, &len, "", 0); break; case VALUE: /* key=value followed by end of string */ add_string (&ret, &len, value, p-value); break; case VALUE_QUOTED: /* unterminated key="value" */ fprintf (stderr, "%s: warning: unterminated quoted string on kernel command line\n", g_get_prgname ()); add_string (&ret, &len, value, p-value); } add_null (&ret, &len); return ret; } char ** parse_proc_cmdline (void) { CLEANUP_FCLOSE FILE *fp = NULL; CLEANUP_FREE char *cmdline = NULL; size_t len = 0; fp = fopen ("/proc/cmdline", "re"); if (fp == NULL) { perror ("/proc/cmdline"); return NULL; } if (getline (&cmdline, &len, fp) == -1) { perror ("getline"); return NULL; } /* 'len' is not the length of the string, but the length of the * buffer. We need to chomp the string. */ len = strlen (cmdline); if (len >= 1 && cmdline[len-1] == '\n') cmdline[len-1] = '\0'; return parse_cmdline_string (cmdline); } const char * get_cmdline_key (char **argv, const char *key) { size_t i; for (i = 0; argv[i] != NULL; i += 2) { if (STREQ (argv[i], key)) return argv[i+1]; } /* Not found. */ return NULL; } virt-p2v-1.42.3/PaxHeaders/virt-p2v-make-kiwi.in0000644000000000000000000000013214267535425016262 xustar0030 mtime=1658764053.832410166 30 atime=1665478155.862244506 30 ctime=1665495228.406332802 virt-p2v-1.42.3/virt-p2v-make-kiwi.in0000644000175000017500000001515514267535425020075 0ustar00rjonesrjones00000000000000#!/bin/bash - # @configure_input@ # virt-p2v-make-kiwi # Copyright (C) 2016 SUSE. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . unset CDPATH program="virt-p2v-make-kiwi" version="@PACKAGE_VERSION@" prefix="@prefix@" exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" # Parse the command line arguments. shortopts=o:V longopts=help,inject-ssh-identity:,long-options,output:,short-options,version TEMP=`getopt \ -o "$shortopts" \ --long "$longopts" \ -n $program -- "$@"` if [ $? != 0 ]; then echo "$program: problem parsing the command line arguments" exit 1 fi eval set -- "$TEMP" usage () { echo "Usage:" echo " $program [--options] [-o kiwi-folder]" echo echo "Read $program(1) man page for more information." exit $1 } output=p2v.kiwi ssh_identity= while true; do case "$1" in --inject-ssh-identity) ssh_identity="$2" shift 2;; -o|--output) output="$2" shift 2;; # help etc. --help) usage 0;; -V|--version) echo "$program $version" exit 0;; --short-options) echo -n "$shortopts" | @SED@ -e 's/://g' -e 's/\(.\)/-\1\n/g' exit 0;; --long-options) echo "$longopts" | @SED@ -e 's/,/\n/g' -e 's/:$//mg' -e 's/\(.*\)/--\1/mg' | grep -v -E -- "--(short|long)-options" exit 0;; --) shift break;; *) echo "internal error ($1)" exit 1;; esac done set -e if [ -n "$VIRT_P2V_DATA_DIR" ]; then datadir="$VIRT_P2V_DATA_DIR" libdir="$VIRT_P2V_DATA_DIR" else datadir="@datadir@/virt-p2v" libdir="@libdir@/virt-p2v" fi # Dependencies. Since kiwi is SUSE-specific, only include # dependencies.suse here. depsfile="$datadir/dependencies.suse" if [ ! -f "$depsfile" ]; then echo "$0: cannot find dependencies file ($depsfile)" exit 1 fi dependencies= while read line; do if [ -n "$line" ]; then depname=$(echo $line | awk '{gsub(/ /, "", $0); print}') pkg=" " if [ -z "$dependencies" ]; then dependencies="$pkg" else dependencies="$dependencies $pkg" fi fi done < $depsfile # Compute the distro-dependent pieces for kiwi branding= release_pkg= base_pattern= kiwi_boot= repos= . /etc/os-release case "$NAME" in SLES) branding="SLE" release_pkg="sles-release" base_pattern="patterns-sles-Minimal" case "$VERSION_ID" in 12) kiwi_boot="SLES12" repos="http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard" ;; 12.1) kiwi_boot="SLES12" repos="http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/Update/standard http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/GA/standard http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard" ;; *) echo "Unsupported distribution $NAME $VERSION_ID" exit 1;; esac;; openSUSE*) branding="openSUSE" release_pkg="openSUSE-release" base_pattern="patterns-openSUSE-base" case "$VERSION" in 13.1\ *) kiwi_boot="13.1" repos="obs://13.1/repo/oss" ;; 13.2\ *) kiwi_boot="13.2" repos="obs://13.2/repo/oss" ;; 42.1) kiwi_boot="leap42.1" repos="obs://leap/42.1/repo/oss" ;; *\ \(Tumbleweed\)) kiwi_boot="leap42.1" repos="obs://openSUSE:Factory/standard" ;; *) echo "Unsupported distribution $NAME $VERSION_ID" exit 1;; esac;; *) echo "Unsupported distribution $NAME $VERSION" exit 1;; esac # Compute the repos repos_xml= for repo in $repos; do repos_xml=" \n \n \n$repos_xml" done mkdir $output cp $datadir/kiwi-config.sh $output/config.sh mkdir -p $output/root/etc/sysconfig/network cat >$output/root/etc/sysconfig/network/ifcfg-eth0 << EOF BOOTPROTO='dhcp' MTU='' REMOTE_IPADDR='' STARTMODE='onboot' EOF mkdir -p $output/root/etc/systemd/system cp $datadir/p2v.service $output/root/etc/systemd/system mkdir -p $output/root/etc/udev/rules.d cat >$output/root/etc/udev/rules.d/70-persistent-net.rules < $output/root/usr/bin/virt-p2v if test "z$ssh_identity" != "z"; then mkdir -p $output/root/var/tmp cp $ssh_identity $output/root/var/tmp/id_rsa chmod 0600 $output/root/var/tmp/id_rsa fi # Now generate the final kiwi config, substituting as necessary. @AWK@ \ -v "dependencies=$dependencies" \ -v "md5sum_virt_p2v=$md5sum_virt_p2v" \ -v "branding=$branding" \ -v "release_pkg=$release_pkg" \ -v "base_pattern=$base_pattern" \ -v "kiwi_boot=$kiwi_boot" \ -v "repos=$repos_xml" \ '{ gsub (/__PACKAGE_NAME__/, "@PACKAGE_NAME@"); gsub (/__PACKAGE_VERSION__/, "@PACKAGE_VERSION@"); gsub (/__PACKAGE_VERSION_FULL__/, "@PACKAGE_VERSION_FULL@"); gsub (//, dependencies); gsub (/__BRANDING__/, branding); gsub (/__RELEASE_PKG__/, release_pkg); gsub (/__BASE_PATTERN__/, base_pattern); gsub (/__KIWI_BOOT__/, kiwi_boot); gsub (//, repos); print; }' \ $datadir/kiwi-config.xml.in > $output/config.xml echo "kiwi config folder written to $output" virt-p2v-1.42.3/PaxHeaders/nbd.c0000644000000000000000000000013214267535425013274 xustar0030 mtime=1658764053.832410166 30 atime=1665478182.890085066 30 ctime=1665495228.432332636 virt-p2v-1.42.3/nbd.c0000644000175000017500000002110114267535425015073 0ustar00rjonesrjones00000000000000/* virt-p2v * Copyright (C) 2009-2019 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* This file handles running L. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "p2v.h" /* How long to wait for nbdkit to start (seconds). */ #define WAIT_NBD_TIMEOUT 10 /* The local port that nbdkit listens on (incremented for each server which is * started). */ static int nbd_local_port; /* Whether nbdkit recognizes "--exit-with-parent". */ static bool nbd_exit_with_parent; static pid_t start_nbdkit (const char *device, int *fds, size_t nr_fds); static int open_listening_socket (int **fds, size_t *nr_fds); static int bind_tcpip_socket (const char *port, int **fds, size_t *nr_fds); static char *nbd_error; static void set_nbd_error (const char *fs, ...) __attribute__((format(printf,1,2))); static void set_nbd_error (const char *fs, ...) { va_list args; char *msg; int len; va_start (args, fs); len = vasprintf (&msg, fs, args); va_end (args); if (len < 0) error (EXIT_FAILURE, errno, "vasprintf (original error format string: %s)", fs); free (nbd_error); nbd_error = msg; } const char * get_nbd_error (void) { return nbd_error; } /** * Check for nbdkit. */ void test_nbd_server (void) { int r; /* Initialize nbd_local_port. */ if (is_iso_environment) /* The p2v ISO should allow us to open up just about any port, so * we can fix a port number in that case. Using a predictable * port number in this case should avoid rare errors if the port * colides with another (ie. it'll either always fail or never * fail). */ nbd_local_port = 50123; else /* When testing on the local machine, choose a random port. */ nbd_local_port = 50000 + (random () % 10000); #if DEBUG_STDERR fprintf (stderr, "checking for nbdkit ...\n"); #endif r = system ("nbdkit file --version" #ifndef DEBUG_STDERR " >/dev/null 2>&1" #endif ); if (r != 0) { fprintf (stderr, _("%s: nbdkit was not found, cannot continue.\n"), g_get_prgname ()); exit (EXIT_FAILURE); } r = system ("nbdkit --exit-with-parent --version" #ifndef DEBUG_STDERR " >/dev/null 2>&1" #endif ); nbd_exit_with_parent = (r == 0); #if DEBUG_STDERR fprintf (stderr, "found nbdkit (%s exit with parent)\n", nbd_exit_with_parent ? "can" : "cannot"); #endif } /** * Start nbdkit. * * We previously tested nbdkit (see C). * * Returns the process ID (E 0) or C<0> if there is an error. */ pid_t start_nbd_server (int *port, const char *device) { int *fds = NULL; size_t i, nr_fds; pid_t pid; *port = open_listening_socket (&fds, &nr_fds); if (*port == -1) return -1; pid = start_nbdkit (device, fds, nr_fds); for (i = 0; i < nr_fds; ++i) close (fds[i]); free (fds); return pid; } #define FIRST_SOCKET_ACTIVATION_FD 3 /** * Set up file descriptors and environment variables for * socket activation. * * Note this function runs in the child between fork and exec. */ static inline void socket_activation (int *fds, size_t nr_fds) { size_t i; char nr_fds_str[20]; char pid_str[16]; if (fds == NULL) return; for (i = 0; i < nr_fds; ++i) { int fd = FIRST_SOCKET_ACTIVATION_FD + i; if (fds[i] != fd) { dup2 (fds[i], fd); close (fds[i]); } } snprintf (nr_fds_str, sizeof nr_fds_str, "%zu", nr_fds); setenv ("LISTEN_FDS", nr_fds_str, 1); snprintf (pid_str, sizeof pid_str, "%d", (int) getpid ()); setenv ("LISTEN_PID", pid_str, 1); } /** * Start a local L process using the * L. * * C and C will contain the locally pre-opened file descriptors * for this. * * Returns the process ID (E 0) or C<0> if there is an error. */ static pid_t start_nbdkit (const char *device, int *fds, size_t nr_fds) { pid_t pid; CLEANUP_FREE char *file_str = NULL; #if DEBUG_STDERR fprintf (stderr, "starting nbdkit for %s using socket activation\n", device); #endif if (asprintf (&file_str, "file=%s", device) == -1) error (EXIT_FAILURE, errno, "asprintf"); pid = fork (); if (pid == -1) { set_nbd_error ("fork: %m"); return 0; } if (pid == 0) { /* Child. */ const char *nofork_opt; close (0); if (open ("/dev/null", O_RDONLY) == -1) { perror ("open: /dev/null"); _exit (EXIT_FAILURE); } socket_activation (fds, nr_fds); nofork_opt = nbd_exit_with_parent ? "--exit-with-parent" : /* don't fork, and exit when the parent * thread does */ "-f"; /* don't fork */ execlp ("nbdkit", "nbdkit", "-r", /* readonly (vital!) */ nofork_opt, "file", /* file plugin */ file_str, /* a device like file=/dev/sda */ NULL); perror ("nbdkit"); _exit (EXIT_FAILURE); } /* Parent. */ return pid; } /** * Open a listening socket on an unused local port and return it. * * Returns the port number on success or C<-1> on error. * * The file descriptor(s) bound are returned in the array *fds, *nr_fds. * The caller must free the array. */ static int open_listening_socket (int **fds, size_t *nr_fds) { int port; char port_str[16]; /* This just ensures we don't try the port we previously bound to. */ port = nbd_local_port; /* Search for a free port. */ for (; port < 60000; ++port) { snprintf (port_str, sizeof port_str, "%d", port); if (bind_tcpip_socket (port_str, fds, nr_fds) == 0) { /* See above. */ nbd_local_port = port + 1; return port; } } set_nbd_error ("cannot find a free local port"); return -1; } static int bind_tcpip_socket (const char *port, int **fds_rtn, size_t *nr_fds_rtn) { struct addrinfo *ai = NULL; struct addrinfo hints; struct addrinfo *a; int err; int *fds = NULL; size_t nr_fds; int addr_in_use = 0; memset (&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo ("localhost", port, &hints, &ai); if (err != 0) { #if DEBUG_STDERR fprintf (stderr, "%s: getaddrinfo: localhost: %s: %s", g_get_prgname (), port, gai_strerror (err)); #endif return -1; } nr_fds = 0; for (a = ai; a != NULL; a = a->ai_next) { int sock, opt; sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (sock == -1) error (EXIT_FAILURE, errno, "socket"); opt = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) == -1) perror ("setsockopt: SO_REUSEADDR"); #ifdef IPV6_V6ONLY if (a->ai_family == PF_INET6) { if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1) perror ("setsockopt: IPv6 only"); } #endif if (bind (sock, a->ai_addr, a->ai_addrlen) == -1) { if (errno == EADDRINUSE) { addr_in_use = 1; close (sock); continue; } perror ("bind"); close (sock); continue; } if (listen (sock, SOMAXCONN) == -1) { perror ("listen"); close (sock); continue; } nr_fds++; fds = realloc (fds, sizeof (int) * nr_fds); if (!fds) error (EXIT_FAILURE, errno, "realloc"); fds[nr_fds-1] = sock; } freeaddrinfo (ai); if (nr_fds == 0 && addr_in_use) { #if DEBUG_STDERR fprintf (stderr, "%s: unable to bind to localhost:%s: %s\n", g_get_prgname (), port, strerror (EADDRINUSE)); #endif return -1; } #if DEBUG_STDERR fprintf (stderr, "%s: bound to localhost:%s (%zu socket(s))\n", g_get_prgname (), port, nr_fds); #endif *fds_rtn = fds; *nr_fds_rtn = nr_fds; return 0; } virt-p2v-1.42.3/PaxHeaders/issue0000644000000000000000000000013214205675260013432 xustar0030 mtime=1645705904.591187538 30 atime=1665494789.829055979 30 ctime=1665495228.444332559 virt-p2v-1.42.3/issue0000644000175000017500000000051714205675260015241 0ustar00rjonesrjones00000000000000virt-p2v - Convert a physical machine to use KVM. *** The root password is "p2v" (without quotes). To see the status of virt-p2v, do: systemctl status p2v -l Virt-p2v may take some time to start up. If virt-p2v is not running after a few minutes, you can start it by typing: launch-virt-p2v *** virt-p2v-1.42.3/PaxHeaders/virt-p2v.pod0000644000000000000000000000013214314553633014554 xustar0030 mtime=1664276379.719307607 30 atime=1665478120.033462845 30 ctime=1665495228.456332483 virt-p2v-1.42.3/virt-p2v.pod0000644000175000017500000007573714314553633016403 0ustar00rjonesrjones00000000000000=head1 NAME virt-p2v - Convert a physical machine to use KVM =head1 SYNOPSIS virt-p2v virt-p2v.iso =head1 DESCRIPTION Virt-p2v converts a physical machine to run virtualized on KVM, managed by libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV), or one of the other targets supported by L. Normally you don’t run the virt-p2v program directly. Instead you have to boot the physical machine using the bootable CD-ROM, ISO or PXE image. This bootable image contains the virt-p2v binary and runs it automatically. Booting from a CD-ROM/etc is required because the disks which are being converted must be quiescent. It is not safe to try to convert a running physical machine where other programs may be modifying the disk content at the same time. This manual page documents running the virt-p2v program. To create the bootable image you should look at L or L. =head1 NETWORK SETUP Virt-p2v runs on the physical machine which you want to convert. It has to talk to another server called the "conversion server" which must have L installed on it. It always talks to the conversion server over SSH: ┌──────────────┐ ┌─────────────────┐ │ virt-p2v │ │ virt-v2v │ │ (physical │ ssh connection │ (conversion │ │ server) ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ server) │ └──────────────┘ └─────────────────┘ The virt-v2v program on the conversion server does the actual conversion (physical to virtual, and virtual to virtual conversions are sufficiently similar that we use the same program to do both). The SSH connection is always initiated from the physical server. All data is transferred over the SSH connection. In terms of firewall and network configuration, you only need to ensure that the physical server has access to a port (usually TCP port 22) on the conversion server. Note that the physical machine may reconnect several times during the conversion process. The reverse port forwarding feature of ssh (ie. C) is required by virt-p2v, and it will not work if this is disabled on the conversion server. (C must be C in the L file on the conversion server). The scp (secure copy) feature of ssh is required by virt-p2v so it can send over small files (this is I the method by which disks are copied). The conversion server does not need to be a physical machine. It could be a virtual machine, as long as it has sufficient memory and disk space to do the conversion, and as long as the physical machine can connect directly to its SSH port. (See also L). Because all of the data on the physical server’s hard drive(s) has to be copied over the network, the speed of conversion is largely determined by the speed of the network between the two machines. =head1 GUI INTERACTIVE CONFIGURATION When you start virt-p2v, you'll see a graphical configuration dialog that walks you through connection to the conversion server, asks for the password, which local hard disks you want to convert, and other things like the name of the guest to create and the number of virtual CPUs to give it. =head2 SSH CONFIGURATION DIALOG When virt-p2v starts up in GUI mode, the first dialog looks like this: ┌─────────────────────────────────────────────────────────────┐ │ virt-p2v │ │ │ │ Conversion server: [____________________________] : [22___] │ │ │ │ User name: [root__________________________________] │ │ │ │ Password: [______________________________________] │ │ │ │ SSH Identity URL: [______________________________________] │ │ │ In the fields above, you must enter the details of the conversion server: the hostname, SSH port number, remote user name, and either the password or SSH identity (private key) URL. The conversion server must have an up to date version of virt-v2v. Normally you must log in to the conversion server as root, but if you check the following box: │ │ │ [ ] Use sudo when running virt-v2v │ │ │ then you can log in as another user, and virt-p2v will use the L command to elevate privileges to root. Note that sudo must not require a password. It is also possible to run virt-v2v on the conversion server entirely as non-root, but output modes may be limited. Consult the L manual page for details. At the bottom of the dialog are these buttons: │ │ │ [ Test connection ] │ │ │ │ [ Configure network ] [ XTerm ] [ About virt-p2v ] [ Next ] │ │ │ └─────────────────────────────────────────────────────────────┘ You must press the C button first to test the SSH connection to the conversion server. If that is successful (ie. you have supplied the correct server name, user name, password, etc., and a suitable version of virt-v2v is available remotely) then press the C button to move to the next dialog. You can use the C button if you need to assign a static IP address to the physical machine, or use Wifi, bonding or other network features. The C button opens a shell which can be used for diagnostics, manual network configuration, and so on. =head2 DISK AND NETWORK CONFIGURATION DIALOG The second configuration dialog lets you configure the details of conversion, including what to convert and where to send the guest. In the left hand column, starting at the top, the target properties let you select the name of the guest (ie. after conversion) and how many virtual CPUs and how much RAM to give it. The defaults come from the physical machine, and you can usually leave them unchanged: ┌─────────────────────────────────────── ─ ─ ─ ─ │ Target properties: │ │ Name: [hostname______________] │ │ # vCPUs: [4_____________________] │ │ Memory (MB): [16384_________________] │ The second panel on the left controls the virt-v2v output options. To understand these options it is a really good idea to read the L manual page. You can leave the options at the default to create a guest as a disk image plus libvirt XML file located in F on the conversion host. This is a good idea if you are a first-time virt-p2v user. │ │ Virt-v2v output options: │ │ Output to (-o): [local ▼] │ │ Output conn. (-oc): [___________________] │ │ Output storage (-os): [/var/tmp___________] │ │ Output format (-of): [___________________] │ │ Output allocation (-oa): [sparse ▼] │ All output options and paths are relative to the conversion server (I to the physical server). Finally in the left hand column is an information box giving the version of virt-p2v (on the physical server) and virt-v2v (on the conversion server). You should supply this information when reporting bugs. In the right hand column are three panels which control what hard disks, removable media devices, and network interfaces, will be created in the output guest. Normally leaving these at the default settings is fine. ─ ─ ──────────────────────────────────────────────────┐ Fixed hard disks │ │ Convert Device │ [✔] sda │ 1024G HITACHI │ s/n 12345 │ [✔] sdb │ 119G HITACHI │ s/n 12346 │ │ Normally you would want to convert all hard disks. If you want virt-p2v to completely ignore a local hard disk, uncheck it. The hard disk that contains the operating system must be selected. If a hard disk is part of a RAID array or LVM volume group (VG), then either all hard disks in that array/VG must be selected, or none of them. │ Removable media │ │ Convert Device │ [✔] sr0 │ │ If the physical machine has CD or DVD drives, then you can use the Removable media panel to create corresponding drives on the guest after conversion. Note that any data CDs/DVDs which are mounted in the drives are I copied over. At the bottom of the dialog, the C button instructs virt-p2v to re-enumerate the fixed hard disks and the removable media drives. (Note that the button will also reset the currently active selections in both of those panels.) This button is useful in combination with the C button on the L: in the XTerm window, you can expose further block devices to the kernel (such as L), and the C button allows virt-p2v to learn about all the block devices again. │ Network interfaces │ │ Convert Device Connect to virtual network │ [✔] em1 [default________________________] │ [ ] wlp3s0 [default________________________] │ │ In the Network interfaces panel, select the network interfaces that should be created in the guest after conversion. You can also connect these to target hypervisor networks (for further information about this feature, see L). On supported hardware, left-clicking on the device name (eg. C) causes a light to start flashing on the physical interface, allowing the interface to be identified by the operator. When you are ready to begin the conversion, press the C button: │ [ Back ] [ Refresh disks ] [ Start conversion ] │ │ ─ ─ ──────────────────────────────────────────────────┘ =head2 CONVERSION RUNNING DIALOG When conversion is running you will see this dialog: ┌────────────────────────────────────────────────────────┐ │ virt-p2v │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ ▲│ │ │ │ │ │ │ │ │ │ ∼ ∼ ∼ ∼ │ │ │ │ │ │ │ │ │ │ ▼│ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ Log files ... to /tmp/virt-p2v-xxx │ │ │ │ Doing conversion ... │ │ │ │ [ Cancel conversion ] │ │ │ └────────────────────────────────────────────────────────┘ In the main scrolling area you will see messages from the virt-v2v process. Below the main area, virt-p2v shows you the location of the directory on the conversion server that contains log files and other debugging information. Below that is the current status and a button for cancelling conversion. Once conversion has finished, you should shut down the physical machine. If conversion is successful, you should never reboot it. =head1 KERNEL COMMAND LINE CONFIGURATION If you don’t want to configure things using the graphical UI, an alternative is to configure through the kernel command line. This is especially convenient if you are converting a lot of physical machines which are booted using PXE. Where exactly you set command line arguments depends on your PXE implementation, but for pxelinux you put them in the C field in the F file. For example: DEFAULT p2v TIMEOUT 20 PROMPT 0 LABEL p2v KERNEL vmlinuz0 APPEND initrd=initrd0.img [....] p2v.server=conv.example.com p2v.password=secret p2v.o=libvirt You have to set some or all of the following command line arguments: =over 4 __KERNEL_CONFIG__ =item B =item B Select a pre-conversion command to run. Any command or script can be specified here. If the command contains spaces, you must quote the whole command with double quotes. The default is not to run any command. =item B =item B =item B =item B Select a post-conversion command to run if conversion is successful. This can be any command or script. If the command contains spaces, you must quote the whole command with double quotes. I virt-p2v is running as root, I the command line was set from F (not I<--cmdline>), then the default is to run the L command. Otherwise the default is not to run any command. =item B =item B Select a post-conversion command to run if conversion fails. Any command or script can be specified here. If the command contains spaces, you must quote the whole command with double quotes. The default is not to run any command. =item B Use DHCP for configuring the network interface (this is the default). =begin comment =item B Set up a static IPv4 network configuration. =end comment =back =head1 SSH IDENTITIES As a somewhat more secure alternative to password authentication, you can use an SSH identity (private key) for authentication. First create a key pair. It must have an empty passphrase: ssh-keygen -t rsa -N '' -f id_rsa This creates a private key (C) and a public key (C) pair. The public key should be appended to the C file on the virt-v2v conversion server (usually to C). For distributing the private key, there are four scenarios from least secure to most secure: =over 4 =item 1. Not using SSH identities at all, ie. password authentication. Anyone who can sniff the PXE boot parameters from the network or observe the password some other way can log in to the virt-v2v conversion server. =item 2. SSH identity embedded in the virt-p2v ISO or disk image. In the GUI, use: │ Password: [ ] │ │ │ │ SSH Identity URL: [file:///var/tmp/id_rsa_____________] │ or on the kernel command line: p2v.identity=file:///var/tmp/id_rsa The SSH private key can still be sniffed from the network if using standard PXE. =item 3. SSH identity downloaded from a website. In the GUI, use: │ Password: [ ] │ │ │ │ SSH Identity URL: [https://internal.example.com/id_rsa] │ or on the kernel command line: p2v.identity=https://internal.example.com/id_rsa Anyone could still download the private key and use it to log in to the virt-v2v conversion server, but you could provide some extra security by configuring the web server to only allow connections from P2V machines. Note that L creates the C (private key) file with mode 0600. If you simply copy the file to a webserver, the webserver will not serve it. It will reply with "403 Forbidden" errors. You will need to change the mode of the file to make it publicly readable, for example by using: chmod 0644 id_rsa =item 4. SSH identity embedded in the virt-p2v ISO or disk image (like 2.), I use of secure PXE, PXE over separate physical network, or sneakernet to distribute virt-p2v to the physical machine. =back Both L and L have the same option I<--inject-ssh-identity> for injecting the private key into the virt-p2v disk image / ISO. See also the following manual sections: L L =head1 ACCESSING ISCSI DEVICES In case the disk that contains the operating system, or other disks that you want to convert, are LUNs of remote iSCSI targets, follow the steps below so that virt-p2v can learn about said disks. Note that this procedure depends on the use of the GUI. The guide below is roughly based on the L. =over 4 =item 1. Open a shell in an XTerm window, using the C button of the L. (Note that the XTerm window(s) persist while you advance to further dialogs in virt-p2v, therefore it's unnecessary to jump back and forth between virt-p2v dialogs just for entering additional shell commands in the XTerm window(s).) =item 2. Using C or another text editor, set the iSCSI initiator name in F, for example: InitiatorName=iqn.1994-05.com.redhat:846e82c634 If the file does not exist, create it. (Remember that this file is part of the virt-p2v Live environment, therefore saving it does not modify any hard disks.) =item 3. Configure any further iSCSI initiator details I that are required by the iSCSI target that you intend to log in to; that is, before you issue the first C command below. This includes the CHAP user name and password if the target authenticates the initiator with CHAP, and the reverse direction CHAP user name and password too, if you want to ascertain the identity of the target on the initiator as well (this is called "mutual authentication"). Completing the configuration at this stage is important because the first C command will start up the C service, and configuration changes with that service already running will not (or may not) take effect until/unless you restart the service using C. =item 4. Discover the iSCSI targets offered by the desired host: iscsiadm -m discovery -t st -p IP_ADDRESS The command should respond with a two-column list of targets. The symbolic target names are in the right hand side column, for example: 10.64.24.179:3260,1 iqn.2006-04.example:444 =item 5. Picking an appropriate target from the right hand side column of the previous step's output, log in to the target: iscsiadm -m node -T TARGET -l This command will inform you whether the login attempt was successful. =item 6. In case the login succeeds, a scan for LUNs on the iSCSI target will commence at once. There are two pitfalls here. One, dependent on network characteristics, the scan may take several (tens of) seconds. Two, even if the login succeeds, ACLs on the target may I prevent the initiator from seeing particular LUNs -- meaning that no new F nodes will appear. This is why it is important to get the initiator name (and, potentially, CHAP authentication) correct at the very beginning of this procedure. Verify the results of the target scan with the C command, and/or with ls -l /dev/disk/by-path/ip-*-iscsi-*-lun-* If these symlinks exist, containing the C from step 4 and the C name from step 5 in their filenames, then the target scan has successfully found the corresponding LUNs. =item 7. Once the remote LUNs have been successfully enumerated, click the C button in the L. =back =head1 COMMON PROBLEMS =head2 Timeouts As described below (see L) virt-p2v makes several long-lived ssh connections to the conversion server. If these connections time out then virt-p2v will fail. To test if a timeout might be causing problems, open an XTerm on the virt-p2v machine, C>, and leave it for at least an hour. If the session disconnects without you doing anything, then there is a timeout which you should turn off. Timeouts happen because: =over 4 =item C or C environment variable Check if one of these environment variables is set in the root shell on the conversion server. =item sshd C setting Check for C settings in C on the conversion server. =item Firewall or NAT settings Check if there is a firewall or NAT box between virt-p2v and the conversion server, and if this firewall drops idle connections after a too-short time. virt-p2v E 1.36 attempts to work around firewall timeouts by sending ssh keepalive messages every 5 minutes. =back =head1 OPTIONS =over 4 =item B<--help> Display help. =item B<--cmdline=CMDLINE> This is used for debugging. Instead of parsing the kernel command line from F, parse the string parameter C. =item B<--colors> =item B<--colours> Use ANSI colour sequences to colourize messages. This is the default when the output is a tty. If the output of the program is redirected to a file, ANSI colour sequences are disabled unless you use this option. =item B<--iso> This flag is passed to virt-p2v when it is launched inside the virt-p2v ISO environment, ie. when it is running on a real physical machine (and thus not when testing). It enables various dangerous features such as the Shutdown popup button. =item B<--test-disk=/PATH/TO/DISK.IMG> For testing or debugging purposes, replace F with a local file. You must use an absolute path. Note that the C button will be disabled in the L of the GUI. =item B<-v> =item B<--verbose> In libguestfs E 1.33.41, debugging is always enabled on the conversion server, and this option does nothing. =item B<-V> =item B<--version> Display version number and exit. =back =head1 HOW VIRT-P2V WORKS B We may change how virt-p2v works at any time in the future. As described above, virt-p2v runs on a physical machine, interrogates the user or the kernel command line for configuration, and then establishes one or more ssh connections to the virt-v2v conversion server. The ssh connections are interactive shell sessions to the remote host, but the commands sent are generated entirely by virt-p2v itself, not by the user. For data transfer, virt-p2v will use the reverse port forward feature of ssh (ie. C). It will first make one or more test connections, which are used to query the remote version of virt-v2v and its features. The test connections are closed before conversion begins. ┌──────────────┐ ┌─────────────────┐ │ virt-p2v │ │ virt-v2v │ │ (physical │ control connection │ (conversion │ │ server) ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ server) │ └──────────────┘ └─────────────────┘ Once virt-p2v is ready to start conversion, it will open a single ssh control connection. It first sends a mkdir command to create a temporary directory on the conversion server. The directory name is randomly chosen and is displayed in the GUI. It has the form: /tmp/virt-p2v-YYYYMMDD-XXXXXXXX where C is the current date, and the ‘X’s are random characters. Into this directory are written various files which include: =over 4 =item F =item F =item F =item F =item F I<(before conversion)> The output of the corresponding commands (ie L, L etc) on the physical machine. The dmesg output is useful for detecting problems such as missing device drivers or firmware on the virt-p2v ISO. The others are useful for debugging novel hardware configurations. =item F I<(before conversion)> The content of the environment where L will run. =item F I<(before conversion)> The name (usually the hostname) of the physical machine. =item F I<(before conversion)> Libvirt XML describing the physical machine. It is used to pass data about the physical source host to L via the I<-i libvirtxml> option. Note this is not "real" libvirt XML (and must B be loaded into libvirt, which would reject it anyhow). Also it is not the same as the libvirt XML which virt-v2v generates in certain output modes. =item F =item F I<(before conversion)> The versions of virt-p2v and virt-v2v respectively. =item F I<(after conversion)> The final status of the conversion. C<0> if the conversion was successful. Non-zero if the conversion failed. =item F