In an effort to reduce the code, start to use few bits of GLib: - replace the gnulib c-type module - replace the gnulib getprogname module - use g_spawn_sync to launch curl, and drop a file reading function Pino Toscano (6): Include glib.h in p2v.h Use g_ascii_isspace instead of c_isspace from gnulib Use g_get_prgname instead of getprogname from gnulib build: remove no more used gnulib modules Use g_spawn_sync to launch curl Remove whole-file.c Makefile.am | 3 +- bootstrap | 2 -- conversion.c | 5 ++- cpuid.c | 4 +-- gui.c | 11 +++--- kernel-cmdline.c | 4 +-- kernel.c | 10 +++--- main.c | 11 +++--- nbd.c | 10 +++--- p2v.h | 5 ++- physical-xml.c | 6 +--- rtc.c | 13 ++++--- ssh.c | 57 ++++++++++++++--------------- whole-file.c | 94 ------------------------------------------------ 14 files changed, 58 insertions(+), 177 deletions(-) delete mode 100644 whole-file.c -- 2.21.0
We already require GTK, and thus GLib; include glib.h in the main header of p2v, so all of p2v can use GLib. --- p2v.h | 2 ++ physical-xml.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/p2v.h b/p2v.h index eb518f7..adace84 100644 --- a/p2v.h +++ b/p2v.h @@ -18,6 +18,8 @@ #ifndef P2V_H #define P2V_H +#include <glib.h> + #include <stdio.h> #include <stdbool.h> diff --git a/physical-xml.c b/physical-xml.c index 1855190..93cdaa0 100644 --- a/physical-xml.c +++ b/physical-xml.c @@ -34,8 +34,6 @@ #include <libxml/xmlwriter.h> -#include <glib.h> - #include "getprogname.h" #include "libxml2-writer-macros.h" -- 2.21.0
Pino Toscano
2019-Dec-03 11:43 UTC
[Libguestfs] [p2v PATCH 2/6] Use g_ascii_isspace instead of c_isspace from gnulib
--- cpuid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpuid.c b/cpuid.c index c12224a..ca000e1 100644 --- a/cpuid.c +++ b/cpuid.c @@ -39,7 +39,6 @@ #include <error.h> #include <libintl.h> -#include "c-ctype.h" #include "getprogname.h" #include "ignore-value.h" @@ -97,7 +96,7 @@ get_lscpu (void) *p = '\0'; key = strdup (line); /* Skip leading whitespace in the value. */ - for (++p; *p && c_isspace (*p); ++p) + for (++p; *p && g_ascii_isspace (*p); ++p) ; value = strdup (p); -- 2.21.0
Pino Toscano
2019-Dec-03 11:43 UTC
[Libguestfs] [p2v PATCH 3/6] Use g_get_prgname instead of getprogname from gnulib
Since main() calls gtk_init(), then g_get_prgname() returns the name of the current program, much like getprogname(). --- conversion.c | 5 ++--- cpuid.c | 1 - gui.c | 11 +++++------ kernel-cmdline.c | 4 +--- kernel.c | 10 ++++------ main.c | 11 +++++------ nbd.c | 10 ++++------ physical-xml.c | 4 +--- rtc.c | 13 ++++++------- ssh.c | 9 ++++----- 10 files changed, 32 insertions(+), 46 deletions(-) diff --git a/conversion.c b/conversion.c index d7e91a8..8daa1d9 100644 --- a/conversion.c +++ b/conversion.c @@ -50,7 +50,6 @@ #include <pthread.h> #include "ignore-value.h" -#include "getprogname.h" #include "miniexpect.h" #include "p2v.h" @@ -269,7 +268,7 @@ start_conversion (struct config *config, #if DEBUG_STDERR fprintf (stderr, "%s: data connection for %s: SSH remote port %d, local port %s:%d\n", - getprogname (), device, + g_get_prgname (), device, data_conns[i].nbd_remote_port, nbd_local_ipaddr, nbd_local_port); #endif @@ -665,6 +664,6 @@ generate_p2v_version_file (const char *p2v_version_file) return; /* non-fatal */ } fprintf (fp, "%s %s\n", - getprogname (), PACKAGE_VERSION_FULL); + g_get_prgname (), PACKAGE_VERSION_FULL); fclose (fp); } diff --git a/cpuid.c b/cpuid.c index ca000e1..84603bb 100644 --- a/cpuid.c +++ b/cpuid.c @@ -39,7 +39,6 @@ #include <error.h> #include <libintl.h> -#include "getprogname.h" #include "ignore-value.h" #include "p2v.h" diff --git a/gui.c b/gui.c index 3463637..227e41d 100644 --- a/gui.c +++ b/gui.c @@ -82,7 +82,6 @@ #pragma GCC diagnostic pop #include "ignore-value.h" -#include "getprogname.h" #include "p2v.h" @@ -213,7 +212,7 @@ create_connection_dialog (struct config *config) char port_str[64]; conn_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (conn_dlg), getprogname ()); + gtk_window_set_title (GTK_WINDOW (conn_dlg), g_get_prgname ()); gtk_window_set_resizable (GTK_WINDOW (conn_dlg), FALSE); /* The main dialog area. */ @@ -638,7 +637,7 @@ about_button_clicked (GtkWidget *w, gpointer data) dialog = gtk_about_dialog_new (); g_object_set (G_OBJECT (dialog), - "program-name", getprogname (), + "program-name", g_get_prgname (), "version", PACKAGE_VERSION_FULL " (" host_cpu ")", "copyright", "\u00A9 2009-2019 Red Hat Inc.", "comments", @@ -732,7 +731,7 @@ create_conversion_dialog (struct config *config) char memory_str[64]; conv_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (conv_dlg), getprogname ()); + 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. @@ -1640,7 +1639,7 @@ create_running_dialog (void) #endif run_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (run_dlg), getprogname ()); + gtk_window_set_title (GTK_WINDOW (run_dlg), g_get_prgname ()); gtk_window_set_resizable (GTK_WINDOW (run_dlg), FALSE); /* The main dialog area. */ @@ -2200,7 +2199,7 @@ notify_ui_callback (int type, const char *data) default: fprintf (stderr, "%s: unknown message during conversion: type=%d data=%s\n", - getprogname (), type, data); + g_get_prgname (), type, data); free (copy); } } diff --git a/kernel-cmdline.c b/kernel-cmdline.c index 008f3f6..33b0e2b 100644 --- a/kernel-cmdline.c +++ b/kernel-cmdline.c @@ -28,8 +28,6 @@ #include <errno.h> #include <error.h> -#include "getprogname.h" - #include "p2v.h" static void @@ -142,7 +140,7 @@ parse_cmdline_string (const char *cmdline) break; case VALUE_QUOTED: /* unterminated key="value" */ fprintf (stderr, "%s: warning: unterminated quoted string on kernel command line\n", - getprogname ()); + g_get_prgname ()); add_string (&ret, &len, value, p-value); } diff --git a/kernel.c b/kernel.c index 7adf659..6fe3a6f 100644 --- a/kernel.c +++ b/kernel.c @@ -34,8 +34,6 @@ #include <sys/types.h> #include <sys/wait.h> -#include "getprogname.h" - #include "p2v.h" static void notify_ui_callback (int type, const char *data); @@ -77,7 +75,7 @@ kernel_conversion (struct config *config, char **cmdline, int cmdline_source) const char *err = get_conversion_error (); fprintf (stderr, "%s: error during conversion: %s\n", - getprogname (), err); + g_get_prgname (), err); p = get_cmdline_key (cmdline, "p2v.fail"); if (p) @@ -106,7 +104,7 @@ notify_ui_callback (int type, const char *data) switch (type) { case NOTIFY_LOG_DIR: ansi_magenta (stdout); - printf ("%s: remote log directory location: ", getprogname ()); + printf ("%s: remote log directory location: ", g_get_prgname ()); ansi_red (stdout); fputs (data, stdout); ansi_restore (stdout); @@ -119,7 +117,7 @@ notify_ui_callback (int type, const char *data) case NOTIFY_STATUS: ansi_magenta (stdout); - printf ("%s: %s", getprogname (), data); + printf ("%s: %s", g_get_prgname (), data); ansi_restore (stdout); putchar ('\n'); break; @@ -127,7 +125,7 @@ notify_ui_callback (int type, const char *data) default: ansi_red (stdout); printf ("%s: unknown message during conversion: type=%d data=%s", - getprogname (), type, data); + g_get_prgname (), type, data); ansi_restore (stdout); putchar ('\n'); } diff --git a/main.c b/main.c index 9039e82..f8d2aa9 100644 --- a/main.c +++ b/main.c @@ -49,7 +49,6 @@ #pragma GCC diagnostic pop #include "ignore-value.h" -#include "getprogname.h" #include "p2v.h" char **all_disks; @@ -89,7 +88,7 @@ usage (int status) { if (status != EXIT_SUCCESS) fprintf (stderr, _("Try ‘%s --help’ for more information.\n"), - getprogname ()); + g_get_prgname ()); else { printf (_("%s: Convert a physical machine to use KVM\n" "Copyright (C) 2009-2019 Red Hat Inc.\n" @@ -105,8 +104,8 @@ usage (int status) " -v|--verbose Verbose messages\n" " -V|--version Display version and exit\n" "For more information, see the manpage %s(1).\n"), - getprogname (), getprogname (), - getprogname ()); + g_get_prgname (), g_get_prgname (), + g_get_prgname ()); } exit (status); } @@ -210,7 +209,7 @@ main (int argc, char *argv[]) break; case 'V': - printf ("%s %s\n", getprogname (), PACKAGE_VERSION_FULL); + printf ("%s %s\n", g_get_prgname (), PACKAGE_VERSION_FULL); exit (EXIT_SUCCESS); case HELP_OPTION: @@ -223,7 +222,7 @@ main (int argc, char *argv[]) if (optind != argc) { fprintf (stderr, _("%s: unused arguments on the command line\n"), - getprogname ()); + g_get_prgname ()); usage (EXIT_FAILURE); } diff --git a/nbd.c b/nbd.c index 3bbde1e..db6228a 100644 --- a/nbd.c +++ b/nbd.c @@ -37,8 +37,6 @@ #include <sys/socket.h> #include <assert.h> -#include "getprogname.h" - #include "p2v.h" /* How long to wait for the NBD server to start (seconds). */ @@ -267,7 +265,7 @@ test_nbd_servers (void) fprintf (stderr, _("%s: no working NBD server was found, cannot continue.\n" "Please check the --nbd option in the virt-p2v(1) man page.\n"), - getprogname ()); + g_get_prgname ()); exit (EXIT_FAILURE); } @@ -582,7 +580,7 @@ bind_tcpip_socket (const char *ipaddr, const char *port, if (err != 0) { #if DEBUG_STDERR fprintf (stderr, "%s: getaddrinfo: %s: %s: %s", - getprogname (), ipaddr ? ipaddr : "<any>", port, + g_get_prgname (), ipaddr ? ipaddr : "<any>", port, gai_strerror (err)); #endif return -1; @@ -637,7 +635,7 @@ bind_tcpip_socket (const char *ipaddr, const char *port, if (nr_fds == 0 && addr_in_use) { #if DEBUG_STDERR fprintf (stderr, "%s: unable to bind to %s:%s: %s\n", - getprogname (), ipaddr ? ipaddr : "<any>", port, + g_get_prgname (), ipaddr ? ipaddr : "<any>", port, strerror (EADDRINUSE)); #endif return -1; @@ -645,7 +643,7 @@ bind_tcpip_socket (const char *ipaddr, const char *port, #if DEBUG_STDERR fprintf (stderr, "%s: bound to IP address %s:%s (%zu socket(s))\n", - getprogname (), ipaddr ? ipaddr : "<any>", port, nr_fds); + g_get_prgname (), ipaddr ? ipaddr : "<any>", port, nr_fds); #endif *fds_rtn = fds; diff --git a/physical-xml.c b/physical-xml.c index 93cdaa0..4e830ea 100644 --- a/physical-xml.c +++ b/physical-xml.c @@ -34,8 +34,6 @@ #include <libxml/xmlwriter.h> -#include "getprogname.h" - #include "libxml2-writer-macros.h" #include "p2v.h" @@ -77,7 +75,7 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns, memkb = config->memory / 1024; - comment (" %s %s ", getprogname (), PACKAGE_VERSION_FULL); + comment (" %s %s ", g_get_prgname (), PACKAGE_VERSION_FULL); comment (" NOTE!\n" diff --git a/rtc.c b/rtc.c index 05d0fae..32d32c8 100644 --- a/rtc.c +++ b/rtc.c @@ -38,7 +38,6 @@ #include <linux/rtc.h> #endif -#include "getprogname.h" #include "ignore-value.h" #include "p2v.h" @@ -48,7 +47,7 @@ void get_rtc_config (struct rtc_config *rtc) { fprintf (stderr, "%s: RTC: compiled without support for /dev/rtc\n", - getprogname ()); + g_get_prgname ()); rtc->offset = 0; rtc->basis = BASIS_UTC; @@ -92,7 +91,7 @@ get_rtc_config (struct rtc_config *rtc) #ifdef DEBUG_STDERR fprintf (stderr, "%s: RTC: %04d-%02d-%02d %02d:%02d:%02d\n", - getprogname (), + g_get_prgname (), rtm.tm_year + 1900, rtm.tm_mon + 1, rtm.tm_mday, rtm.tm_hour, rtm.tm_min, rtm.tm_sec); #endif @@ -117,7 +116,7 @@ get_rtc_config (struct rtc_config *rtc) #ifdef DEBUG_STDERR fprintf (stderr, "%s: RTC: %ld system time: %ld difference: %g\n", - getprogname (), + g_get_prgname (), (long) rtc_time, (long) system_time, rf); #endif @@ -129,7 +128,7 @@ get_rtc_config (struct rtc_config *rtc) if (rf < -12*60*60 || rf > 14*60*60) { fprintf (stderr, "%s: RTC: offset of RTC from UTC is out of range (%g).\n", - getprogname (), rf); + g_get_prgname (), rf); return; } @@ -137,7 +136,7 @@ get_rtc_config (struct rtc_config *rtc) #ifdef DEBUG_STDERR fprintf (stderr, "%s: RTC: offset of RTC from UTC = %d secs\n", - getprogname (), rtc->offset); + g_get_prgname (), rtc->offset); #endif /* Is the hardware clock set to localtime? @@ -154,7 +153,7 @@ get_rtc_config (struct rtc_config *rtc) rtc->basis = BASIS_LOCALTIME; rtc->offset = 0; #ifdef DEBUG_STDERR - fprintf (stderr, "%s: RTC time is localtime\n", getprogname ()); + fprintf (stderr, "%s: RTC time is localtime\n", g_get_prgname ()); #endif } diff --git a/ssh.c b/ssh.c index 99eefbd..3cd6c71 100644 --- a/ssh.c +++ b/ssh.c @@ -54,7 +54,6 @@ #include <signal.h> #include "ignore-value.h" -#include "getprogname.h" #include "miniexpect.h" #include "p2v.h" @@ -143,7 +142,7 @@ compile_regexps (void) pcre_fullinfo ((re), NULL, PCRE_INFO_OKPARTIAL, &p); \ if (p != 1) { \ fprintf (stderr, "%s: %s:%d: internal error: pattern '%s' cannot be used for partial matching\n", \ - getprogname (), \ + g_get_prgname (), \ __FILE__, __LINE__, (pattern)); \ abort (); \ } \ @@ -813,7 +812,7 @@ test_connection (struct config *config) v2v_version = strndup (&h->buffer[ovector[2]], ovector[3]-ovector[2]); #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v version: %s\n", - getprogname (), v2v_version); + g_get_prgname (), v2v_version); #endif break; @@ -895,7 +894,7 @@ test_connection (struct config *config) case 101: /* virt-v2v supports --colours option */ #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v supports --colours option\n", - getprogname ()); + g_get_prgname ()); #endif feature_colours_option = 1; break; @@ -1009,7 +1008,7 @@ add_option (const char *type, char ***drivers, const char *name, size_t len) #if DEBUG_STDERR fprintf (stderr, "%s: remote virt-v2v supports %s driver %s\n", - getprogname (), type, (*drivers)[n-1]); + g_get_prgname (), type, (*drivers)[n-1]); #endif } -- 2.21.0
Pino Toscano
2019-Dec-03 11:43 UTC
[Libguestfs] [p2v PATCH 4/6] build: remove no more used gnulib modules
Unfortunately they are still used by other modules. --- bootstrap | 2 -- 1 file changed, 2 deletions(-) diff --git a/bootstrap b/bootstrap index db9c8e1..565d504 100755 --- a/bootstrap +++ b/bootstrap @@ -98,9 +98,7 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool <$gnulib_tool || exit modules=' -c-ctype error -getprogname ignore-value manywarnings ptsname_r -- 2.21.0
Pino Toscano
2019-Dec-03 11:44 UTC
[Libguestfs] [p2v PATCH 5/6] Use g_spawn_sync to launch curl
Instead of using system() with stderr redirected to file, use the GLib function g_spawn_sync() to run curl with no need for a shell, and directly collecting stderr as a string. The only behaviour change is that a failure when spawning curl is now logged as error, instead of aborting the whole p2v. --- ssh.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/ssh.c b/ssh.c index 3cd6c71..9dd2d8a 100644 --- a/ssh.c +++ b/ssh.c @@ -210,17 +210,15 @@ static int curl_download (const char *url, const char *local_file) { char curl_config_file[] = "/tmp/curl.XXXXXX"; - char error_file[] = "/tmp/curlerr.XXXXXX"; - CLEANUP_FREE char *error_message = NULL; - int fd, r; + int fd; size_t i, len; FILE *fp; - CLEANUP_FREE char *curl_cmd = NULL; - - fd = mkstemp (error_file); - if (fd == -1) - error (EXIT_FAILURE, errno, "mkstemp: %s", error_file); - close (fd); + 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); @@ -246,31 +244,29 @@ curl_download (const char *url, const char *local_file) fclose (fp); /* Run curl to download the URL to a file. */ - if (asprintf (&curl_cmd, "curl -f -s -S -o %s -K %s 2>%s", - local_file, curl_config_file, error_file) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - r = system (curl_cmd); + 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 (r == -1) - error (EXIT_FAILURE, errno, "system: %s", curl_cmd); + 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 (r) && WEXITSTATUS (r) != 0) { - if (read_whole_file (error_file, &error_message, NULL) == 0) - set_ssh_error ("%s: %s", url, error_message); - else - set_ssh_error ("%s: curl error %d", url, WEXITSTATUS (r)); - unlink (error_file); + if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) != 0) { + set_ssh_error ("%s: %s", url, stderr); return -1; } - else if (!WIFEXITED (r)) { - set_ssh_internal_error ("curl subprocess got a signal (%d)", r); - unlink (error_file); + else if (!WIFEXITED (exit_status)) { + set_ssh_internal_error ("curl subprocess got a signal (%d)", exit_status); return -1; } - unlink (error_file); return 0; } -- 2.21.0
The only function in it, read_whole_file(), is not used anymore. (And anyway, the GLib function g_file_get_contents() can be used instead.) --- Makefile.am | 3 +- p2v.h | 3 -- whole-file.c | 94 ---------------------------------------------------- 3 files changed, 1 insertion(+), 99 deletions(-) delete mode 100644 whole-file.c diff --git a/Makefile.am b/Makefile.am index 02e3288..7649511 100644 --- a/Makefile.am +++ b/Makefile.am @@ -124,8 +124,7 @@ virt_p2v_SOURCES = \ physical-xml.c \ rtc.c \ ssh.c \ - utils.c \ - whole-file.c + utils.c generated_sources = \ config.c \ diff --git a/p2v.h b/p2v.h index adace84..a14edc5 100644 --- a/p2v.h +++ b/p2v.h @@ -125,9 +125,6 @@ extern char *get_if_addr (const char *if_name); extern char *get_if_vendor (const char *if_name, int truncate); extern void wait_network_online (const struct config *); -/* whole-file.c */ -extern int read_whole_file (const char *filename, char **data_r, size_t *size_r); - /* virt-v2v version and features (read from remote). */ extern char *v2v_version; diff --git a/whole-file.c b/whole-file.c deleted file mode 100644 index 156bb9b..0000000 --- a/whole-file.c +++ /dev/null @@ -1,94 +0,0 @@ -/* libguestfs - * Copyright (C) 2011-2019 Red Hat Inc. - * - * 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 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 program. If not, see <https://www.gnu.org/licenses/>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <libintl.h> - -#include "p2v.h" - -/** - * Read the whole file into a memory buffer and return it. The file - * should be a regular, local, trusted file. - */ -int -read_whole_file (const char *filename, char **data_r, size_t *size_r) -{ - int fd; - char *data; - off_t size; - off_t n; - ssize_t r; - struct stat statbuf; - - fd = open (filename, O_RDONLY|O_CLOEXEC); - if (fd == -1) { - fprintf (stderr, "open: %s: %m\n", filename); - return -1; - } - - if (fstat (fd, &statbuf) == -1) { - fprintf (stderr, "stat: %s: %m\n", filename); - close (fd); - return -1; - } - - size = statbuf.st_size; - data = malloc (size + 1); - if (data == NULL) { - perror ("malloc"); - return -1; - } - - n = 0; - while (n < size) { - r = read (fd, &data[n], size - n); - if (r == -1) { - fprintf (stderr, "read: %s: %m\n", filename); - free (data); - close (fd); - return -1; - } - if (r == 0) { - fprintf (stderr, "read: %s: unexpected end of file\n", filename); - free (data); - close (fd); - return -1; - } - n += r; - } - - if (close (fd) == -1) { - fprintf (stderr, "close: %s: %m\n", filename); - free (data); - return -1; - } - - /* For convenience of callers, \0-terminate the data. */ - data[size] = '\0'; - - *data_r = data; - if (size_r != NULL) - *size_r = size; - - return 0; -} -- 2.21.0
Richard W.M. Jones
2019-Dec-04 10:00 UTC
Re: [Libguestfs] [p2v PATCH 6/6] Remove whole-file.c
Simpifies things a bit, especially the function to run curl without using a temporary file, and the function to read a whole file. ACK series, Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
Reasonably Related Threads
- [PATCH] p2v: Calculate offset of the Real Time Clock from UTC.
- [PATCH 0/3] Use gnulib's getprogname
- [PATCH 0/2] Remove virt-p2v from libguestfs
- [PATCH] p2v: Calculate offset of the Real Time Clock from UTC.
- [PATCH 0/3] p2v, v2v: Ensure the full version is always available in several places.