mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5011bea96d | ||
|
|
31740229dc | ||
|
|
69305ca07b | ||
|
|
77e447a516 | ||
|
|
39d4437e29 | ||
|
|
503e9fde5a | ||
|
|
0818f31960 | ||
|
|
fd6263df75 | ||
|
|
ce4bfa5d08 | ||
|
|
389c6b7583 | ||
|
|
48607d9d15 | ||
|
|
3bff5a6f79 | ||
|
|
2d2eba643d | ||
|
|
8d4d35c604 | ||
|
|
92c2e1e79e | ||
|
|
2bc54b40f7 | ||
|
|
47c2233026 | ||
|
|
065c997f5b | ||
|
|
2fc54b8121 | ||
|
|
91578639c6 | ||
|
|
ff4467a1a4 | ||
|
|
a47c923b05 | ||
|
|
25c321a8fd | ||
|
|
cb233a73c6 | ||
|
|
9b890de878 | ||
|
|
08503c2482 | ||
|
|
9451c1a2ef | ||
|
|
5a4977fc66 | ||
|
|
50701c8325 | ||
|
|
358d17dea1 |
53
.github/workflows/main.yml
vendored
53
.github/workflows/main.yml
vendored
@@ -3,9 +3,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'ci/**' # Allow automatic CI testing on ci/* branches
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch: # Allow manual triggering on any branch
|
||||
|
||||
# Runs basic configure, make and make check.
|
||||
jobs:
|
||||
@@ -38,7 +40,8 @@ jobs:
|
||||
run: |
|
||||
# Git is needed to run git submodule command.
|
||||
# json-c is missing from the Ubuntu package deps.
|
||||
sudo apt-get -y install git libjson-c-dev
|
||||
# python libvirt module used unconditionally in a python test
|
||||
sudo apt-get -y install git libjson-c-dev python3-libvirt
|
||||
|
||||
- name: Fix broken Ubuntu kernel permissions
|
||||
run: |
|
||||
@@ -59,7 +62,9 @@ jobs:
|
||||
- name: Compile the code
|
||||
run: |
|
||||
autoreconf -fiv
|
||||
./configure --enable-werror
|
||||
# --disable-ruby needed for
|
||||
# https://github.com/libguestfs/libguestfs/issues/309
|
||||
./configure --enable-werror --disable-ruby
|
||||
make -j
|
||||
|
||||
- name: Run the quick test
|
||||
@@ -99,7 +104,7 @@ jobs:
|
||||
|
||||
container:
|
||||
image: quay.io/fedora/fedora:${{ matrix.release }}
|
||||
options: --security-opt seccomp=unconfined
|
||||
options: --privileged
|
||||
|
||||
steps:
|
||||
- name: Identify the system
|
||||
@@ -119,43 +124,41 @@ jobs:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Create user
|
||||
run: |
|
||||
useradd -m -s /bin/bash -G wheel guestfs
|
||||
tail /etc/passwd
|
||||
|
||||
- name: Make checkout directory editable by the sscg user
|
||||
run: |
|
||||
chown -R guestfs:wheel ${GITHUB_WORKSPACE}
|
||||
|
||||
- name: Checkout submodule
|
||||
run: |
|
||||
su -c 'git submodule update --init' guestfs
|
||||
git config --global --add safe.directory $PWD
|
||||
git submodule update --init
|
||||
|
||||
- name: Compile the code
|
||||
run: |
|
||||
su -c '
|
||||
autoreconf -fiv &&
|
||||
./configure CFLAGS="-fPIC -g -O2" --enable-werror &&
|
||||
make -j
|
||||
' guestfs
|
||||
|
||||
- name: Run the quick test
|
||||
run: |
|
||||
su -c 'make quickcheck' guestfs
|
||||
make quickcheck
|
||||
|
||||
- name: Sanity check libvirt connection
|
||||
run: |
|
||||
virtqemud --daemon
|
||||
virsh uri
|
||||
|
||||
- name: Run the full tests
|
||||
run: |
|
||||
# error: passt exited with status 1
|
||||
export SKIP_TEST_NETWORK_SH=1
|
||||
# error: passt exited with status 1
|
||||
# guestunmount exit(3) doesn't trigger for root user
|
||||
# https://github.com/libguestfs/libguestfs/issues/307
|
||||
export SKIP_TEST_GUESTUNMOUNT_FD=1
|
||||
|
||||
# test-fuse-unmount-race.sh is flakey:
|
||||
# ./test-fuse-umount-race.sh: wait for guestmount to exit failed after 10 seconds
|
||||
export SKIP_TEST_FUSE_UMOUNT_RACE_SH=1
|
||||
|
||||
# test-rsync.sh is busted for root user
|
||||
# rsync_out: '/dir2/' to 'rsync://root@169.254.2.2:65257/dest/': rsync: [generator] failed to set times on "." (in dest): Operation not permitted (1)
|
||||
export SKIP_TEST_RSYNC_SH=1
|
||||
# error: internal_autosync: umount: /sysroot: umount: /sysroot:
|
||||
# target is busy
|
||||
export SKIP_RHBZ1011907_1165785_SH=1
|
||||
# We have to set $HOME since su -p won't set it below.
|
||||
export HOME=/home/guestfs
|
||||
if ! su -p -c 'make check' guestfs; then
|
||||
|
||||
if ! make check; then
|
||||
find -name test-suite.log -exec cat {} \;
|
||||
exit 1
|
||||
fi
|
||||
|
||||
2
common
2
common
Submodule common updated: 3ac5d18419...30d3e92130
11
configure.ac
11
configure.ac
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2025 Red Hat Inc.
|
||||
# Copyright (C) 2009-2026 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
|
||||
@@ -20,8 +20,8 @@
|
||||
# freeform string.
|
||||
m4_define([libguestfs_major], [1])
|
||||
m4_define([libguestfs_minor], [59])
|
||||
m4_define([libguestfs_release], [3])
|
||||
m4_define([release_date], [2026-02-11])
|
||||
m4_define([libguestfs_release], [4])
|
||||
m4_define([release_date], [2026-03-17])
|
||||
|
||||
AC_INIT([libguestfs],libguestfs_major.libguestfs_minor.libguestfs_release)
|
||||
AC_SUBST([RELEASE_DATE],release_date)
|
||||
@@ -127,10 +127,6 @@ dnl The appliance and any dependencies.
|
||||
HEADING([Checking the appliance and its dependencies])
|
||||
m4_include([m4/guestfs-appliance.m4])
|
||||
|
||||
dnl Check for QEMU.
|
||||
HEADING([Checking for QEMU])
|
||||
m4_include([m4/guestfs-qemu.m4])
|
||||
|
||||
dnl Miscellaneous libraries used by other programs.
|
||||
HEADING([Checking for other libraries])
|
||||
m4_include([m4/guestfs-misc-libraries.m4])
|
||||
@@ -312,7 +308,6 @@ feature ()
|
||||
|
||||
feature "Daemon" test "x$enable_daemon" = "xyes"
|
||||
feature "Appliance" test "x$ENABLE_APPLIANCE" = "xyes"
|
||||
print "QEMU" "$QEMU"
|
||||
feature "guestfish" true ;# always enabled
|
||||
feature "FUSE filesystem" test "x$enable_fuse" = "xyes"
|
||||
print "Default backend" "$DEFAULT_BACKEND"
|
||||
|
||||
@@ -342,7 +342,7 @@ do_aug_match (const char *path)
|
||||
vp = realloc (matches, sizeof (char *) * (r+1));
|
||||
if (vp == NULL) {
|
||||
reply_with_perror ("realloc");
|
||||
free (vp);
|
||||
free_stringslen (matches, r);
|
||||
return NULL;
|
||||
}
|
||||
matches = vp;
|
||||
|
||||
@@ -102,7 +102,6 @@ test_blkid_p_i_opt (void)
|
||||
r = commandr (NULL, &err, "blkid", "-p", "/dev/null", NULL);
|
||||
if (r == -1) {
|
||||
/* This means we couldn't run the blkid command at all. */
|
||||
command_failed:
|
||||
reply_with_error ("could not run 'blkid' command: %s", err);
|
||||
return -1;
|
||||
}
|
||||
@@ -112,8 +111,10 @@ test_blkid_p_i_opt (void)
|
||||
}
|
||||
|
||||
r = commandr (NULL, &err2, "blkid", "-i", NULL);
|
||||
if (r == -1)
|
||||
goto command_failed;
|
||||
if (r == -1) {
|
||||
reply_with_error ("could not run 'blkid' command: %s", err2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strstr (err2, "invalid option --")) {
|
||||
return 0;
|
||||
|
||||
@@ -164,6 +164,7 @@ debug_fds (const char *subcmd, size_t argc, char *const *const argv)
|
||||
if (!dir) {
|
||||
reply_with_perror ("opendir: /proc/self/fd");
|
||||
fclose (fp);
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -501,7 +501,10 @@ do_zfile (const char *method, const char *path)
|
||||
if (len > 0 && line[len-1] == '\n')
|
||||
line[len-1] = '\0';
|
||||
|
||||
return strdup (line);
|
||||
char *ret = strdup (line);
|
||||
if (ret == NULL)
|
||||
reply_with_perror ("strdup");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
||||
@@ -331,6 +331,7 @@ do_inotify_files (void)
|
||||
pp = popen (cmd, "w");
|
||||
if (pp == NULL) {
|
||||
reply_with_perror ("sort");
|
||||
close (fd);
|
||||
unlink (tempfile);
|
||||
return NULL;
|
||||
}
|
||||
@@ -339,6 +340,7 @@ do_inotify_files (void)
|
||||
events = do_inotify_read ();
|
||||
if (events == NULL) {
|
||||
pclose (pp);
|
||||
close (fd);
|
||||
unlink (tempfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -771,6 +771,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
r = command (NULL, &err, "lvm", "vgcfgbackup", "-f", tmp, vg, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("vgcfgbackup: %s", err);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -778,6 +779,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
fd = open (tmp, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_error ("%s", tmp);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -796,6 +798,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
reply_with_error ("metadata is too large for message buffer");
|
||||
free (buf);
|
||||
close (fd);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
buf2 = realloc (buf, alloc);
|
||||
@@ -803,6 +806,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
reply_with_perror ("realloc");
|
||||
free (buf);
|
||||
close (fd);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
buf = buf2;
|
||||
@@ -813,6 +817,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
reply_with_perror ("read: %s", tmp);
|
||||
free (buf);
|
||||
close (fd);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
if (rs == 0)
|
||||
@@ -824,6 +829,7 @@ do_vgmeta (const char *vg, size_t *size_r)
|
||||
if (close (fd) == -1) {
|
||||
reply_with_perror ("close: %s", tmp);
|
||||
free (buf);
|
||||
unlink (tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
10
fish/rc.c
10
fish/rc.c
@@ -277,6 +277,11 @@ rc_listen (void)
|
||||
receive_stdout (s);
|
||||
|
||||
fp = fdopen (s, "r+");
|
||||
if (fp == NULL) {
|
||||
perror ("fdopen");
|
||||
close (s);
|
||||
abort ();
|
||||
}
|
||||
xdrstdio_create (&xdr, fp, XDR_DECODE);
|
||||
|
||||
if (!xdr_guestfish_hello (&xdr, &hello)) {
|
||||
@@ -393,6 +398,11 @@ rc_remote (int pid, const char *cmd, size_t argc, char *argv[],
|
||||
|
||||
/* Send the greeting. */
|
||||
fp = fdopen (sock, "r+");
|
||||
if (fp == NULL) {
|
||||
perror ("fdopen");
|
||||
close (sock);
|
||||
return -1;
|
||||
}
|
||||
xdrstdio_create (&xdr, fp, XDR_ENCODE);
|
||||
|
||||
if (!xdr_guestfish_hello (&xdr, &hello)) {
|
||||
|
||||
@@ -33,9 +33,6 @@ let non_daemon_functions = [
|
||||
depends on the backend, but is usually the location of the
|
||||
qemu/KVM hypervisor.
|
||||
|
||||
The default is chosen when the library was compiled by the
|
||||
configure script.
|
||||
|
||||
You can also override this by setting the C<LIBGUESTFS_HV>
|
||||
environment variable.
|
||||
|
||||
@@ -59,8 +56,12 @@ the qemu binary at the same time as the handle is created.|} };
|
||||
longdesc = "\
|
||||
Return the current hypervisor binary.
|
||||
|
||||
This is always non-NULL. If it wasn't set already, then this will
|
||||
return the default qemu binary name." };
|
||||
If it wasn't set already, then this will return the default
|
||||
qemu binary name.
|
||||
|
||||
For some backends this may return an error if called before
|
||||
launch since it may not be possible to get the default hypervisor
|
||||
before the appliance is launched." };
|
||||
|
||||
{ defaults with
|
||||
name = "set_path"; added = (0, 0, 3);
|
||||
|
||||
@@ -34,9 +34,6 @@ let non_daemon_functions = [
|
||||
shortdesc = "set the hypervisor binary (usually qemu)";
|
||||
longdesc = {|Set the hypervisor binary (usually qemu) that we will use.
|
||||
|
||||
The default is chosen when the library was compiled by the
|
||||
configure script.
|
||||
|
||||
You can also override this by setting the C<LIBGUESTFS_HV>
|
||||
environment variable.
|
||||
|
||||
@@ -55,10 +52,6 @@ the qemu binary at the same time as the handle is created.|} };
|
||||
style = RConstString "hv", [], [];
|
||||
blocking = false;
|
||||
deprecated_by = Replaced_by "get_hv";
|
||||
tests = [
|
||||
InitNone, Always, TestRun (
|
||||
[["get_qemu"]]), []
|
||||
];
|
||||
shortdesc = "get the hypervisor binary (usually qemu)";
|
||||
longdesc = "\
|
||||
Return the current hypervisor binary (usually qemu).
|
||||
|
||||
@@ -99,7 +99,6 @@ jnilib_LTLIBRARIES = libguestfs_jni.la
|
||||
jnilibdir = $(JNI_INSTALL_DIR)
|
||||
|
||||
libguestfs_jni_la_SOURCES = \
|
||||
com_redhat_et_libguestfs_GuestFS.h \
|
||||
actions-0.c \
|
||||
actions-1.c \
|
||||
actions-2.c \
|
||||
|
||||
@@ -820,6 +820,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g,
|
||||
|
||||
/* ... else the old hotplugging case */
|
||||
error (g, _("hotplugging support was removed in libguestfs 1.48"));
|
||||
free_drive_struct (drv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1385,6 +1385,7 @@ xac_insert (guestfs_h *g,
|
||||
entry = malloc (sizeof *entry);
|
||||
if (entry == NULL) {
|
||||
perrorf (g, "malloc");
|
||||
guestfs_free_xattr_list (xattrs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1393,6 +1394,7 @@ xac_insert (guestfs_h *g,
|
||||
if (entry->c.pathname == NULL) {
|
||||
perrorf (g, "malloc");
|
||||
free (entry);
|
||||
guestfs_free_xattr_list (xattrs);
|
||||
return -1;
|
||||
}
|
||||
if (STREQ (path, "/"))
|
||||
@@ -1418,6 +1420,7 @@ rlc_insert (guestfs_h *g,
|
||||
entry = malloc (sizeof *entry);
|
||||
if (entry == NULL) {
|
||||
perrorf (g, "malloc");
|
||||
free (link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1426,6 +1429,7 @@ rlc_insert (guestfs_h *g,
|
||||
if (entry->c.pathname == NULL) {
|
||||
perrorf (g, "malloc");
|
||||
free (entry);
|
||||
free (link);
|
||||
return -1;
|
||||
}
|
||||
if (STREQ (path, "/"))
|
||||
|
||||
@@ -164,4 +164,9 @@ extern int accept4 (int sockfd, struct sockaddr *__restrict__ addr,
|
||||
extern int pipe2 (int pipefd[2], int flags);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CAML_UNIX_ERROR
|
||||
/* For backwards compatibility with OCaml < 5.0 */
|
||||
#define caml_unix_error unix_error
|
||||
#endif
|
||||
|
||||
#endif /* GUESTFS_INTERNAL_ALL_H_ */
|
||||
|
||||
@@ -331,6 +331,11 @@ struct backend_ops {
|
||||
*/
|
||||
char *(*create_cow_overlay) (guestfs_h *g, void *data, struct drive *drv);
|
||||
|
||||
/* Get the default hypervisor (qemu), if the user does not override
|
||||
* this by calling guestfs_set_hv or setting LIBGUESTFS_HV.
|
||||
*/
|
||||
const char *(*get_default_hv) (guestfs_h *g, void *data);
|
||||
|
||||
/* Launch and shut down. */
|
||||
int (*launch) (guestfs_h *g, void *data, const char *arg);
|
||||
int (*shutdown) (guestfs_h *g, void *data, int check_for_errors);
|
||||
@@ -791,7 +796,7 @@ void guestfs_int_init_libvirt_backend (void) __attribute__((constructor));
|
||||
#endif
|
||||
|
||||
/* qemu.c */
|
||||
extern int guestfs_int_platform_has_kvm (guestfs_h *g);
|
||||
extern int guestfs_int_platform_has_kvm (guestfs_h *g, const char *qemu);
|
||||
extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src);
|
||||
extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv);
|
||||
extern char *guestfs_int_qemu_escape_param (guestfs_h *g, const char *param);
|
||||
|
||||
51
lib/handle.c
51
lib/handle.c
@@ -118,17 +118,6 @@ guestfs_create_flags (unsigned flags, ...)
|
||||
g->path = strdup (GUESTFS_DEFAULT_PATH);
|
||||
if (!g->path) goto error;
|
||||
|
||||
#ifdef QEMU
|
||||
g->hv = strdup (QEMU);
|
||||
#else
|
||||
/* configure --without-qemu, so set QEMU to something which will
|
||||
* definitely fail. The user is expected to override the hypervisor
|
||||
* by setting an environment variable or calling set_hv.
|
||||
*/
|
||||
g->hv = strdup ("false");
|
||||
#endif
|
||||
if (!g->hv) goto error;
|
||||
|
||||
/* Get program name. */
|
||||
if (STRPREFIX (getprogname (), "lt-"))
|
||||
/* Remove libtool (lt-*) prefix from short name. */
|
||||
@@ -535,27 +524,17 @@ guestfs_impl_get_path (guestfs_h *g)
|
||||
int
|
||||
guestfs_impl_set_qemu (guestfs_h *g, const char *qemu)
|
||||
{
|
||||
char *new_hv;
|
||||
|
||||
/* Only this deprecated set_qemu API supports using NULL as a
|
||||
* parameter, to mean set it back to the default QEMU. The new
|
||||
* set_hv API does not allow callers to do this.
|
||||
/* This deprecated API let you set qemu == NULL to mean "use the
|
||||
* default qemu". set_hv doesn't allow this, although maybe it
|
||||
* should.
|
||||
*/
|
||||
if (qemu == NULL) {
|
||||
#ifdef QEMU
|
||||
new_hv = safe_strdup (g, QEMU);
|
||||
#else
|
||||
error (g, _("configured --without-qemu so calling guestfs_set_qemu with qemu == NULL is an error"));
|
||||
return -1;
|
||||
#endif
|
||||
free (g->hv);
|
||||
g->hv = NULL;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
new_hv = safe_strdup (g, qemu);
|
||||
|
||||
free (g->hv);
|
||||
g->hv = new_hv;
|
||||
|
||||
return 0;
|
||||
return guestfs_impl_set_hv (g, qemu);
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -575,7 +554,21 @@ guestfs_impl_set_hv (guestfs_h *g, const char *hv)
|
||||
char *
|
||||
guestfs_impl_get_hv (guestfs_h *g)
|
||||
{
|
||||
return safe_strdup (g, g->hv);
|
||||
if (g->hv)
|
||||
return safe_strdup (g, g->hv);
|
||||
else {
|
||||
/* Try to return the default hypervisor. */
|
||||
const char *default_hv;
|
||||
|
||||
if (g->backend_ops && g->backend_data &&
|
||||
(default_hv = g->backend_ops->get_default_hv (g, g->backend_data))
|
||||
!= NULL)
|
||||
return safe_strdup (g, default_hv);
|
||||
else {
|
||||
error (g, _("cannot get default hypervisor"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
/* Per-handle data. */
|
||||
struct backend_direct_data {
|
||||
const char *qemu; /* Qemu binary name. */
|
||||
pid_t pid; /* Qemu PID. */
|
||||
pid_t recoverypid; /* Recovery process PID. */
|
||||
|
||||
@@ -441,6 +442,23 @@ free_pid_path:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Pick a default, arch-specific qemu. */
|
||||
static const char *
|
||||
get_default_hv_direct (guestfs_h *g, void *datav)
|
||||
{
|
||||
if (host_cpu[0] == 'i' && strchr ("3456", host_cpu[1]) &&
|
||||
host_cpu[2] == '8' && host_cpu[3] == '6' && host_cpu[4] == '\0')
|
||||
return "qemu-system-i386";
|
||||
else if (STRPREFIX (host_cpu, "arm"))
|
||||
return "qemu-system-arm";
|
||||
else if (STREQ (host_cpu, "powerpc64") ||
|
||||
STREQ (host_cpu, "powerpc64le") ||
|
||||
STREQ (host_cpu, "ppc64le"))
|
||||
return "qemu-system-ppc64";
|
||||
else
|
||||
return "qemu-system-" host_cpu;
|
||||
}
|
||||
|
||||
static int
|
||||
launch_direct (guestfs_h *g, void *datav, const char *arg)
|
||||
{
|
||||
@@ -482,20 +500,23 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
|
||||
|
||||
guestfs_int_launch_send_progress (g, 3);
|
||||
|
||||
data->qemu = g->hv ? : get_default_hv_direct (g, data);
|
||||
debug (g, "chosen qemu: %s", data->qemu);
|
||||
|
||||
debug (g, "begin testing qemu features");
|
||||
|
||||
/* If debugging, print the qemu version. */
|
||||
if (g->verbose) {
|
||||
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
|
||||
|
||||
guestfs_int_cmd_add_arg (cmd, g->hv);
|
||||
guestfs_int_cmd_add_arg (cmd, data->qemu);
|
||||
guestfs_int_cmd_add_arg (cmd, "-version");
|
||||
guestfs_int_cmd_set_stdout_callback (cmd, debug_lines, NULL, 0);
|
||||
guestfs_int_cmd_run (cmd);
|
||||
}
|
||||
|
||||
/* Work out if KVM is supported or if the user wants to force TCG. */
|
||||
if ((has_kvm = guestfs_int_platform_has_kvm (g)) == -1)
|
||||
if ((has_kvm = guestfs_int_platform_has_kvm (g, data->qemu)) == -1)
|
||||
goto cleanup0;
|
||||
debug (g, "qemu KVM: %s", has_kvm ? "enabled" : "disabled");
|
||||
|
||||
@@ -571,7 +592,7 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
|
||||
perrorf (g, "qemuopts");
|
||||
goto cleanup0;
|
||||
}
|
||||
if (qemuopts_set_binary (qopts, g->hv) == -1) goto qemuopts_error;
|
||||
if (qemuopts_set_binary (qopts, data->qemu) == -1) goto qemuopts_error;
|
||||
|
||||
/* CVE-2011-4127 mitigation: Disable SCSI ioctls on virtio-blk
|
||||
* devices.
|
||||
@@ -857,8 +878,8 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
|
||||
if (g->pgroup)
|
||||
setpgid (0, 0);
|
||||
|
||||
execve (g->hv, argv, env); /* Run qemu. */
|
||||
perror (g->hv);
|
||||
execvpe (data->qemu, argv, env); /* Run qemu. */
|
||||
perror (data->qemu);
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -1061,7 +1082,7 @@ shutdown_direct (guestfs_h *g, void *datav, int check_for_errors)
|
||||
if (guestfs_int_wait4 (g, data->pid, &status, &rusage, "qemu") == -1)
|
||||
ret = -1;
|
||||
else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) {
|
||||
guestfs_int_external_command_failed (g, status, g->hv, NULL);
|
||||
guestfs_int_external_command_failed (g, status, data->qemu, NULL);
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
@@ -1105,6 +1126,7 @@ max_disks_direct (guestfs_h *g, void *datav)
|
||||
static struct backend_ops backend_direct_ops = {
|
||||
.data_size = sizeof (struct backend_direct_data),
|
||||
.create_cow_overlay = create_cow_overlay_direct,
|
||||
.get_default_hv = get_default_hv_direct,
|
||||
.launch = launch_direct,
|
||||
.shutdown = shutdown_direct,
|
||||
.get_pid = get_pid_direct,
|
||||
|
||||
@@ -154,7 +154,6 @@ struct libvirt_xml_params {
|
||||
size_t appliance_index; /* index of appliance */
|
||||
bool enable_svirt; /* false if we decided to disable sVirt */
|
||||
bool current_proc_is_root; /* true = euid is root */
|
||||
bool is_custom; /* true if user sets non-default g->hv */
|
||||
};
|
||||
|
||||
static int parse_capabilities (guestfs_h *g, const char *capabilities_xml, struct backend_libvirt_data *data);
|
||||
@@ -167,7 +166,6 @@ static void debug_appliance_permissions (guestfs_h *g);
|
||||
static void debug_socket_permissions (guestfs_h *g);
|
||||
static void libvirt_error (guestfs_h *g, const char *fs, ...) __attribute__((format (printf,2,3)));
|
||||
static void libvirt_debug (guestfs_h *g, const char *fs, ...) __attribute__((format (printf,2,3)));
|
||||
static int is_custom_hv (guestfs_h *g, struct backend_libvirt_data *data);
|
||||
static int is_blk (const char *path);
|
||||
static void ignore_errors (void *ignore, virErrorPtr ignore2);
|
||||
static void set_socket_create_context (guestfs_h *g);
|
||||
@@ -305,6 +303,13 @@ create_cow_overlay_libvirt (guestfs_h *g, void *datav, struct drive *drv)
|
||||
return overlay;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_default_hv_libvirt (guestfs_h *g, void *datav)
|
||||
{
|
||||
struct backend_libvirt_data *data = datav;
|
||||
return data->default_qemu;
|
||||
}
|
||||
|
||||
static int
|
||||
launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
|
||||
{
|
||||
@@ -567,8 +572,12 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
|
||||
params.appliance_index = g->nr_drives;
|
||||
strcpy (params.appliance_dev, "/dev/sd");
|
||||
guestfs_int_drive_name (params.appliance_index, ¶ms.appliance_dev[7]);
|
||||
params.is_custom = is_custom_hv (g, data);
|
||||
params.enable_svirt = !params.is_custom;
|
||||
|
||||
/* Disable sVirt if the user set a custom hypervisor because SELinux
|
||||
* rules probably refer to a specific qemu binary (or label) which a
|
||||
* custom hypervisor probably doesn't have.
|
||||
*/
|
||||
params.enable_svirt = g->hv == NULL;
|
||||
|
||||
/* workaround a libvirt validation bug that rejects disabling selinux
|
||||
* at domain level and also at disk level, as of libvirt 11.8.0
|
||||
@@ -873,24 +882,6 @@ parse_domcapabilities (guestfs_h *g, const char *domcapabilities_xml,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_custom_hv (guestfs_h *g, struct backend_libvirt_data *data)
|
||||
{
|
||||
CLEANUP_FREE char *rawpath = NULL;
|
||||
|
||||
if (STREQ (g->hv, data->default_qemu))
|
||||
return 0;
|
||||
|
||||
/* ignore error here, let guest startup fail later */
|
||||
rawpath = realpath(g->hv, NULL);
|
||||
if (rawpath && STREQ (rawpath, data->default_qemu))
|
||||
return 0;
|
||||
|
||||
debug (g, "user passed custom hv=%s (realpath=%s) libvirt default=%s",
|
||||
g->hv, rawpath, data->default_qemu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if HAVE_LIBSELINUX
|
||||
|
||||
/* Set sVirt (SELinux) socket create context. For details see:
|
||||
@@ -1296,7 +1287,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
|
||||
/* Path to hypervisor. Only write this if the user has changed the
|
||||
* default, otherwise allow libvirt to choose the best one.
|
||||
*/
|
||||
if (params->is_custom)
|
||||
if (g->hv)
|
||||
single_element ("emulator", g->hv);
|
||||
|
||||
/* Add a random number generator (backend for virtio-rng). */
|
||||
@@ -2211,6 +2202,7 @@ max_disks_libvirt (guestfs_h *g, void *datav)
|
||||
static struct backend_ops backend_libvirt_ops = {
|
||||
.data_size = sizeof (struct backend_libvirt_data),
|
||||
.create_cow_overlay = create_cow_overlay_libvirt,
|
||||
.get_default_hv = get_default_hv_libvirt,
|
||||
.launch = launch_libvirt,
|
||||
.shutdown = shutdown_libvirt,
|
||||
.max_disks = max_disks_libvirt,
|
||||
|
||||
16
lib/proto.c
16
lib/proto.c
@@ -219,17 +219,19 @@ check_daemon_socket (guestfs_h *g)
|
||||
/* Read and process progress messages that happen during FileIn. */
|
||||
if (flag == GUESTFS_PROGRESS_FLAG) {
|
||||
char mbuf[PROGRESS_MESSAGE_SIZE];
|
||||
guestfs_progress message;
|
||||
guestfs_progress message = { 0 };
|
||||
|
||||
n = g->conn->ops->read_data (g, g->conn, mbuf, PROGRESS_MESSAGE_SIZE);
|
||||
if (n <= 0) /* 0 or -1 */
|
||||
return n;
|
||||
|
||||
xdrmem_create (&xdr, mbuf, PROGRESS_MESSAGE_SIZE, XDR_DECODE);
|
||||
xdr_guestfs_progress (&xdr, &message);
|
||||
if (!xdr_guestfs_progress (&xdr, &message))
|
||||
message.proc = 0;
|
||||
xdr_destroy (&xdr);
|
||||
|
||||
guestfs_int_progress_message_callback (g, &message);
|
||||
if (message.proc)
|
||||
guestfs_int_progress_message_callback (g, &message);
|
||||
|
||||
goto again;
|
||||
}
|
||||
@@ -625,14 +627,16 @@ guestfs_int_recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
|
||||
return -1;
|
||||
|
||||
if (*size_rtn == GUESTFS_PROGRESS_FLAG) {
|
||||
guestfs_progress message;
|
||||
guestfs_progress message = { 0 };
|
||||
XDR xdr;
|
||||
|
||||
xdrmem_create (&xdr, *buf_rtn, PROGRESS_MESSAGE_SIZE, XDR_DECODE);
|
||||
xdr_guestfs_progress (&xdr, &message);
|
||||
if (!xdr_guestfs_progress (&xdr, &message))
|
||||
message.proc = 0;
|
||||
xdr_destroy (&xdr);
|
||||
|
||||
guestfs_int_progress_message_callback (g, &message);
|
||||
if (message.proc)
|
||||
guestfs_int_progress_message_callback (g, &message);
|
||||
|
||||
free (*buf_rtn);
|
||||
*buf_rtn = NULL;
|
||||
|
||||
26
lib/qemu.c
26
lib/qemu.c
@@ -59,7 +59,8 @@ cleanup_json_object_put (void *ptr)
|
||||
* Run a generic QMP test on the QEMU binary.
|
||||
*/
|
||||
static int
|
||||
generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
|
||||
generic_qmp_test (guestfs_h *g,
|
||||
const char *qemu, const char *qmp_command, char **outp)
|
||||
{
|
||||
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
|
||||
int r, fd;
|
||||
@@ -68,6 +69,8 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
|
||||
size_t allocsize = 0;
|
||||
ssize_t len;
|
||||
unsigned lineno;
|
||||
const char *errmsg;
|
||||
CLEANUP_FREE char *errors = NULL;
|
||||
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, "echo ");
|
||||
/* QMP is modal. You have to send the qmp_capabilities command first. */
|
||||
@@ -79,7 +82,7 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, "'{ \"execute\": \"quit\" }' ");
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, " | ");
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, "QEMU_AUDIO_DRV=none ");
|
||||
guestfs_int_cmd_add_string_quoted (cmd, g->hv);
|
||||
guestfs_int_cmd_add_string_quoted (cmd, qemu);
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, " -display none");
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, " -machine none,accel=kvm:hvf:tcg");
|
||||
guestfs_int_cmd_add_string_unquoted (cmd, " -qmp stdio");
|
||||
@@ -108,8 +111,8 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
|
||||
if (len >= 0) debug (g, "generic_qmp_test: %u: %s", lineno, line);
|
||||
if (len == -1 || strstr (line, "\"QMP\"") == NULL) {
|
||||
parse_failure:
|
||||
error (g, "did not understand QMP monitor output from %s", g->hv);
|
||||
return -1;
|
||||
errmsg = "did not understand QMP monitor output";
|
||||
goto err;
|
||||
}
|
||||
|
||||
lineno++; /* line 2 */
|
||||
@@ -133,11 +136,16 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
|
||||
r = guestfs_int_cmd_pipe_wait (cmd);
|
||||
/* QMP tests are optional, don't fail if the tests fail. */
|
||||
if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) {
|
||||
error (g, "%s wait failed or unexpected exit status", g->hv);
|
||||
return -1;
|
||||
errmsg = "wait failed or unexpected exit status";
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
errors = guestfs_int_cmd_get_pipe_errors (cmd);
|
||||
error (g, "%s: %s\nError output of qemu: %s", qemu, errmsg, errors);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,11 +192,11 @@ parse_has_kvm (guestfs_h *g, const char *json)
|
||||
* that command.
|
||||
*/
|
||||
int
|
||||
guestfs_int_platform_has_kvm (guestfs_h *g)
|
||||
guestfs_int_platform_has_kvm (guestfs_h *g, const char *qemu)
|
||||
{
|
||||
char *query_kvm;
|
||||
CLEANUP_FREE char *query_kvm = NULL;
|
||||
|
||||
if (generic_qmp_test (g, "query-kvm", &query_kvm) == -1)
|
||||
if (generic_qmp_test (g, qemu, "query-kvm", &query_kvm) == -1)
|
||||
return -1;
|
||||
|
||||
return parse_has_kvm (g, query_kvm);
|
||||
|
||||
@@ -71,12 +71,14 @@ set_abs_path (guestfs_h *g, const char *ctxstr,
|
||||
if (stat (ret, &statbuf) == -1) {
|
||||
perrorf (g, "%s: %s: %s: stat",
|
||||
_("setting temporary directory"), ctxstr, tmpdir);
|
||||
free (ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR (statbuf.st_mode)) {
|
||||
error (g, _("%s: %s: ‘%s’ is not a directory"),
|
||||
_("setting temporary directory"), ctxstr, tmpdir);
|
||||
free (ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,25 @@ lualibdir = $(libdir)/lua/$(LUA_VERSION)
|
||||
|
||||
generator_built = \
|
||||
bindtests.lua \
|
||||
lua-guestfs.c
|
||||
lua-guestfs.c \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(generator_built) \
|
||||
run-bindtests
|
||||
run-bindtests \
|
||||
tests/010-load.lua \
|
||||
tests/015-globals.lua \
|
||||
tests/020-create.lua \
|
||||
tests/025-create-flags.lua \
|
||||
tests/027-create-multiple.lua \
|
||||
tests/030-config.lua \
|
||||
tests/050-lvcreate.lua \
|
||||
tests/060-readdir.lua \
|
||||
tests/070-optargs.lua \
|
||||
tests/400-events.lua \
|
||||
tests/400-progress.lua \
|
||||
tests/900-errors.lua \
|
||||
$(NULL)
|
||||
|
||||
CLEANFILES += \
|
||||
guestfs.so
|
||||
@@ -85,20 +99,6 @@ TESTS += \
|
||||
tests/400-progress.lua
|
||||
endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
tests/010-load.lua \
|
||||
tests/015-globals.lua \
|
||||
tests/020-create.lua \
|
||||
tests/025-create-flags.lua \
|
||||
tests/027-create-multiple.lua \
|
||||
tests/030-config.lua \
|
||||
tests/050-lvcreate.lua \
|
||||
tests/060-readdir.lua \
|
||||
tests/070-optargs.lua \
|
||||
tests/400-events.lua \
|
||||
tests/400-progress.lua \
|
||||
tests/900-errors.lua
|
||||
|
||||
# Run the tests under valgrind.
|
||||
# This doesn't work. Because Lua dlcloses the library on exit, the
|
||||
# stack traces contain no useful information. The only way to make
|
||||
|
||||
@@ -191,3 +191,19 @@ if test "x$INSTALL_OCAMLLIB" = "x"; then
|
||||
INSTALL_OCAMLLIB=$OCAMLLIB
|
||||
fi
|
||||
AC_SUBST([INSTALL_OCAMLLIB])
|
||||
|
||||
dnl Check if OCaml has caml_unix_error (added 2022, OCaml 5.0).
|
||||
AC_MSG_CHECKING([for caml_unix_error])
|
||||
cat >conftest.c <<'EOF'
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/unixsupport.h>
|
||||
int main () { char *p = (void *) caml_unix_error; return 0; }
|
||||
EOF
|
||||
AS_IF([$OCAMLC conftest.c >&AS_MESSAGE_LOG_FD 2>&1],[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_CAML_UNIX_ERROR],[1],
|
||||
[caml_unix_error found at compile time.])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
rm -f conftest.c conftest.o
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2025 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.
|
||||
|
||||
dnl Check for QEMU for running binaries on this $host_cpu, fall
|
||||
dnl back to basic 'qemu'. Allow the user to override it.
|
||||
AS_CASE([$host_cpu],
|
||||
[i@<:@456@:>@86],[qemu_cpu=i386],
|
||||
[arm*],[qemu_cpu=arm],
|
||||
[amd64],[qemu_cpu=x86_64],
|
||||
[powerpc64 | ppc64le | powerpc64le],[qemu_cpu=ppc64],
|
||||
[qemu_cpu=$host_cpu])
|
||||
default_qemu="qemu-kvm kvm qemu-system-$qemu_cpu qemu"
|
||||
AC_ARG_WITH([qemu],
|
||||
[AS_HELP_STRING([--with-qemu="bin1 bin2 ..."],
|
||||
[set default QEMU binary @<:@default="[qemu-kvm] qemu-system-<host> qemu"@:>@])],
|
||||
dnl --with-qemu or --without-qemu:
|
||||
[],
|
||||
dnl neither option was given:
|
||||
[with_qemu="$default_qemu"]
|
||||
)
|
||||
|
||||
AS_IF([test "x$with_qemu" = "xno"],[
|
||||
AC_MSG_WARN([qemu was disabled, libguestfs may not work at all])
|
||||
QEMU=no
|
||||
],[
|
||||
AC_PATH_PROGS([QEMU],[$with_qemu],[no],
|
||||
[$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/libexec])
|
||||
test "x$QEMU" = "xno" && AC_MSG_ERROR([qemu must be installed])
|
||||
|
||||
AC_DEFINE_UNQUOTED([QEMU],["$QEMU"],[Location of qemu binary.])
|
||||
|
||||
dnl Check that the chosen qemu has virtio-serial support.
|
||||
dnl For historical reasons this can be disabled by setting
|
||||
dnl vmchannel_test=no.
|
||||
if test "x$vmchannel_test" != "xno"; then
|
||||
AC_MSG_CHECKING([that $QEMU -help works])
|
||||
if $QEMU -help >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE(
|
||||
[$QEMU -help: command failed.
|
||||
|
||||
This could be a very old version of qemu, or qemu might not be
|
||||
working.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([that $QEMU -version works])
|
||||
if $QEMU -version >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE(
|
||||
[$QEMU -version: command failed.
|
||||
|
||||
This could be a very old version of qemu, or qemu might not be
|
||||
working.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for $QEMU version >= 1])
|
||||
if $QEMU -version | grep -sq 'version @<:@1-9@:>@'; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE([$QEMU version must be >= 1.0.])
|
||||
fi
|
||||
|
||||
dnl Unfortunately $QEMU -device \? won't just work. We probably
|
||||
dnl need to add a cocktail of different arguments which differ
|
||||
dnl on the various emulators. Thanks, qemu.
|
||||
AC_MSG_CHECKING([what extra options we need to use for qemu feature tests])
|
||||
QEMU_OPTIONS_FOR_CONFIGURE=
|
||||
# Note: the order we test these matters.
|
||||
for opt in "-machine virt" "-machine accel=kvm:tcg" "-display none"; do
|
||||
if $QEMU $QEMU_OPTIONS_FOR_CONFIGURE $opt -device \? >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
QEMU_OPTIONS_FOR_CONFIGURE="$QEMU_OPTIONS_FOR_CONFIGURE $opt"
|
||||
fi
|
||||
done
|
||||
AC_MSG_RESULT([$QEMU_OPTIONS_FOR_CONFIGURE])
|
||||
|
||||
AC_MSG_CHECKING([that $QEMU $QEMU_OPTIONS_FOR_CONFIGURE -device ? works])
|
||||
if $QEMU $QEMU_OPTIONS_FOR_CONFIGURE -device \? >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE([$QEMU $QEMU_OPTIONS_FOR_CONFIGURE -device ? doesn't work.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for virtio-serial support in $QEMU])
|
||||
if $QEMU $QEMU_OPTIONS_FOR_CONFIGURE -device \? 2>&1 | grep -sq virtio-serial; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE(
|
||||
[I did not find virtio-serial support in
|
||||
$QEMU.
|
||||
|
||||
virtio-serial support in qemu or KVM is essential for libguestfs
|
||||
to operate.
|
||||
|
||||
Usually this means that you have to install a newer version of qemu
|
||||
and/or KVM. Please read the relevant section in the README file for
|
||||
more information about this.
|
||||
|
||||
You can override this test by setting the environment variable
|
||||
vmchannel_test=no
|
||||
|
||||
However if you don't have the right support in your qemu, then this
|
||||
just delays the pain.
|
||||
|
||||
If I am using the wrong qemu or you want to compile qemu from source
|
||||
and install it in another location, then you should configure with
|
||||
the --with-qemu option.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
@@ -193,7 +193,13 @@ guestfs_int_ocaml_strings_val (guestfs_h *g, value sv)
|
||||
if (r == NULL) caml_raise_out_of_memory ();
|
||||
for (i = 0; i < Wosize_val (sv); ++i) {
|
||||
r[i] = strdup (String_val (Field (sv, i)));
|
||||
if (r[i] == NULL) caml_raise_out_of_memory ();
|
||||
if (r[i] == NULL) {
|
||||
size_t j;
|
||||
for (j = 0; j < i; ++j)
|
||||
free (r[j]);
|
||||
free (r);
|
||||
caml_raise_out_of_memory ();
|
||||
}
|
||||
}
|
||||
r[i] = NULL;
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ SUBDIRS = $(linguas_translated)
|
||||
|
||||
libguestfs-docs.pot:
|
||||
cd $(top_srcdir) && $(PO4A_UPDATEPO) \
|
||||
--no-deprecation \
|
||||
-o no-warn-simple \
|
||||
-f pod \
|
||||
-M utf-8 \
|
||||
--package-name $(PACKAGE_NAME) \
|
||||
|
||||
@@ -188,6 +188,8 @@ virt-p2v.1: virt-p2v.pod virt-p2v-kernel-config.pod
|
||||
%.pod: $(srcdir)/../$(LINGUA).po
|
||||
rm -f $@ $@-t
|
||||
$(guestfs_am_v_po4a_translate)$(PO4A_TRANSLATE) \
|
||||
--no-deprecation \
|
||||
-o no-warn-simple \
|
||||
-f pod \
|
||||
-M utf-8 -L utf-8 \
|
||||
-k 0 \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,10 +6,10 @@
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libguestfs 1.59.3\n"
|
||||
"Project-Id-Version: libguestfs 1.59.4\n"
|
||||
"Report-Msgid-Bugs-To: https://bugzilla.redhat.com/enter_bug.cgi?"
|
||||
"component=libguestfs&product=Virtualization+Tools\n"
|
||||
"POT-Creation-Date: 2026-02-11 12:07+0000\n"
|
||||
"POT-Creation-Date: 2026-03-17 19:07+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -103,42 +103,42 @@ msgstr ""
|
||||
msgid "Enter key or passphrase (\"%s\"): "
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:145
|
||||
#: common/options/keys.c:146
|
||||
#, c-format
|
||||
msgid "size_t overflow"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:192
|
||||
#: common/options/keys.c:193
|
||||
#, c-format
|
||||
msgid "could not read key from user"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:231
|
||||
#: common/options/keys.c:232
|
||||
#, c-format
|
||||
msgid "selector '%s': missing ID"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:238
|
||||
#: common/options/keys.c:239
|
||||
#, c-format
|
||||
msgid "selector '%s': missing TYPE"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:244
|
||||
#: common/options/keys.c:245
|
||||
#, c-format
|
||||
msgid "selector '%s': missing KEY_STRING, or too many fields"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:253
|
||||
#: common/options/keys.c:254
|
||||
#, c-format
|
||||
msgid "selector '%s': missing FILENAME, or too many fields"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:261
|
||||
#: common/options/keys.c:262
|
||||
#, c-format
|
||||
msgid "selector '%s': too many fields"
|
||||
msgstr ""
|
||||
|
||||
#: common/options/keys.c:263
|
||||
#: common/options/keys.c:264
|
||||
#, c-format
|
||||
msgid "selector '%s': invalid TYPE"
|
||||
msgstr ""
|
||||
@@ -3063,29 +3063,29 @@ msgstr ""
|
||||
msgid "‘%s’ is not a directory or has insecure owner or permissions"
|
||||
msgstr ""
|
||||
|
||||
#: fish/rc.c:283
|
||||
#: fish/rc.c:288
|
||||
#, c-format
|
||||
msgid "guestfish: protocol error: could not read ‘hello’ message\n"
|
||||
msgstr ""
|
||||
|
||||
#: fish/rc.c:288
|
||||
#: fish/rc.c:293
|
||||
#, c-format
|
||||
msgid ""
|
||||
"guestfish: protocol error: version mismatch, server version ‘%s’ does not "
|
||||
"match client version ‘%s’. The two versions must match exactly.\n"
|
||||
msgstr ""
|
||||
|
||||
#: fish/rc.c:373 fish/rc.c:387
|
||||
#: fish/rc.c:378 fish/rc.c:392
|
||||
#, c-format
|
||||
msgid "guestfish: remote: looks like the server is not running\n"
|
||||
msgstr ""
|
||||
|
||||
#: fish/rc.c:399 fish/rc.c:413
|
||||
#: fish/rc.c:409 fish/rc.c:423
|
||||
#, c-format
|
||||
msgid "guestfish: protocol error: could not send initial greeting to server\n"
|
||||
msgstr ""
|
||||
|
||||
#: fish/rc.c:424
|
||||
#: fish/rc.c:434
|
||||
#, c-format
|
||||
msgid "guestfish: protocol error: could not decode reply from server\n"
|
||||
msgstr ""
|
||||
@@ -3700,16 +3700,16 @@ msgstr ""
|
||||
msgid "unknown protocol ‘%s’"
|
||||
msgstr ""
|
||||
|
||||
#: lib/drives.c:822 lib/drives.c:908
|
||||
#: lib/drives.c:822 lib/drives.c:909
|
||||
msgid "hotplugging support was removed in libguestfs 1.48"
|
||||
msgstr ""
|
||||
|
||||
#: lib/drives.c:979
|
||||
#: lib/drives.c:980
|
||||
#, c-format
|
||||
msgid "%s: device not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/drives.c:989
|
||||
#: lib/drives.c:990
|
||||
msgid "drive index out of range"
|
||||
msgstr ""
|
||||
|
||||
@@ -3821,53 +3821,51 @@ msgstr ""
|
||||
msgid "could not initialize dir cache hashtables"
|
||||
msgstr ""
|
||||
|
||||
#: lib/fuse.c:1513
|
||||
#: lib/fuse.c:1517
|
||||
msgid ""
|
||||
"FUSE is not supported in this build of libguestfs because libfuse was not "
|
||||
"found when libguestfs was compiled"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:144
|
||||
#: lib/handle.c:133
|
||||
msgid ""
|
||||
"libguestfs was built with an invalid default backend, using ‘direct’ instead"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:146
|
||||
#: lib/handle.c:135
|
||||
msgid "‘direct’ backend does not work"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:204 lib/handle.c:214
|
||||
#: lib/handle.c:193 lib/handle.c:203
|
||||
#, c-format
|
||||
msgid "%s=%s: non-boolean value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:256
|
||||
#: lib/handle.c:245
|
||||
msgid "non-numeric value for LIBGUESTFS_MEMSIZE"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:337
|
||||
#: lib/handle.c:326
|
||||
#, c-format
|
||||
msgid "guestfs_close: called twice on the same handle\n"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:548
|
||||
msgid ""
|
||||
"configured --without-qemu so calling guestfs_set_qemu with qemu == NULL is "
|
||||
"an error"
|
||||
#: lib/handle.c:568
|
||||
msgid "cannot get default hypervisor"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:601
|
||||
#: lib/handle.c:594
|
||||
#, c-format
|
||||
msgid "too small value for memsize (must be at least %d)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:718
|
||||
#: lib/handle.c:711
|
||||
msgid ""
|
||||
"identifier must contain only alphanumeric characters, underscore or minus "
|
||||
"sign"
|
||||
msgstr ""
|
||||
|
||||
#: lib/handle.c:824
|
||||
#: lib/handle.c:817
|
||||
msgid "setting not found"
|
||||
msgstr ""
|
||||
|
||||
@@ -3899,7 +3897,7 @@ msgstr ""
|
||||
msgid "size of %s is unreasonably large (%<PRIi64> bytes)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:154
|
||||
#: lib/launch-direct.c:155
|
||||
#, c-format
|
||||
msgid ""
|
||||
"current user is not a member of the KVM group (group ID %d). This user "
|
||||
@@ -3908,31 +3906,31 @@ msgid ""
|
||||
"might need to log out and log in again)."
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:390
|
||||
#: lib/launch-direct.c:391
|
||||
#, c-format
|
||||
msgid "passt was killed with signal %d"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:395
|
||||
#: lib/launch-direct.c:396
|
||||
#, c-format
|
||||
msgid "internal error: unexpected exit status from passt (%d)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:402
|
||||
#: lib/launch-direct.c:403
|
||||
#, c-format
|
||||
msgid "passt exited with status %d"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:423
|
||||
#: lib/launch-direct.c:424
|
||||
#, c-format
|
||||
msgid "failed to parse passt PID from '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:472
|
||||
#: lib/launch-direct.c:490
|
||||
msgid "you must call guestfs_add_drive before guestfs_launch"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-direct.c:1005 lib/launch-libvirt.c:663
|
||||
#: lib/launch-direct.c:1026 lib/launch-libvirt.c:672
|
||||
msgid "qemu launched and contacted daemon, but state != READY"
|
||||
msgstr ""
|
||||
|
||||
@@ -3941,56 +3939,56 @@ msgstr ""
|
||||
msgid "%s:%d: error constructing libvirt XML near call to \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:212
|
||||
#: lib/launch-libvirt.c:210
|
||||
msgid ""
|
||||
"could not auto-detect the format.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"‘--format’ option, or via the optional ‘format’ argument to ‘add-drive’."
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:223
|
||||
#: lib/launch-libvirt.c:221
|
||||
msgid ""
|
||||
"could not auto-detect the format when using a non-file protocol.\n"
|
||||
"If the format is known, pass the format to libguestfs, eg. using the\n"
|
||||
"‘--format’ option, or via the optional ‘format’ argument to ‘add-drive’."
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:338
|
||||
#: lib/launch-libvirt.c:343
|
||||
msgid "direct mode flag is not supported yet for libvirt backend"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:372
|
||||
#: lib/launch-libvirt.c:377
|
||||
#, c-format
|
||||
msgid "could not connect to libvirt (URI = %s)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:393
|
||||
#: lib/launch-libvirt.c:398
|
||||
msgid "could not get libvirt capabilities"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:414
|
||||
#: lib/launch-libvirt.c:419
|
||||
msgid "could not get libvirt domain capabilities"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:596
|
||||
#: lib/launch-libvirt.c:605
|
||||
msgid "could not create appliance through libvirt. Original error from libvirt"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:728
|
||||
#: lib/launch-libvirt.c:737
|
||||
msgid "unable to parse capabilities XML returned by libvirt"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:734 lib/launch-libvirt.c:836 lib/libvirt-domain.c:397
|
||||
#: lib/launch-libvirt.c:743 lib/launch-libvirt.c:845 lib/libvirt-domain.c:397
|
||||
#: lib/libvirt-domain.c:481
|
||||
msgid "unable to create new XPath context"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:744 lib/launch-libvirt.c:844 lib/launch-libvirt.c:860
|
||||
#: lib/launch-libvirt.c:753 lib/launch-libvirt.c:853 lib/launch-libvirt.c:869
|
||||
#, c-format
|
||||
msgid "unable to evaluate XPath expression: %s"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:783
|
||||
#: lib/launch-libvirt.c:792
|
||||
#, c-format
|
||||
msgid ""
|
||||
"libvirt hypervisor doesn’t support qemu or KVM,\n"
|
||||
@@ -4005,47 +4003,47 @@ msgid ""
|
||||
"For further help, read the guestfs(3) man page and libguestfs FAQ."
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:830
|
||||
#: lib/launch-libvirt.c:839
|
||||
msgid "unable to parse domain capabilities XML returned by libvirt"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1461 lib/launch-libvirt.c:1709 lib/qemu.c:289
|
||||
#: lib/launch-libvirt.c:1452 lib/launch-libvirt.c:1700 lib/qemu.c:297
|
||||
#, c-format
|
||||
msgid "realpath: could not convert ‘%s’ to absolute path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1539
|
||||
#: lib/launch-libvirt.c:1530
|
||||
msgid ""
|
||||
"libvirt does not support the qemu curl driver protocols (ftp, http, etc.); "
|
||||
"try setting LIBGUESTFS_BACKEND=direct"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1899
|
||||
#: lib/launch-libvirt.c:1890
|
||||
msgid "could not define libvirt secret"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1910
|
||||
#: lib/launch-libvirt.c:1901
|
||||
msgid "rbd protocol secret must be base64 encoded"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1914
|
||||
#: lib/launch-libvirt.c:1905
|
||||
#, c-format
|
||||
msgid "base64_decode_alloc: %m"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1932
|
||||
#: lib/launch-libvirt.c:1923
|
||||
msgid "could not set libvirt secret value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:1945
|
||||
#: lib/launch-libvirt.c:1936
|
||||
msgid "could not get UUID from libvirt secret"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:2121
|
||||
#: lib/launch-libvirt.c:2112
|
||||
msgid "could not destroy libvirt domain"
|
||||
msgstr ""
|
||||
|
||||
#: lib/launch-libvirt.c:2142 lib/launch-libvirt.c:2175
|
||||
#: lib/launch-libvirt.c:2133 lib/launch-libvirt.c:2166
|
||||
#, c-format
|
||||
msgid "%s: internal error forming error message"
|
||||
msgstr ""
|
||||
@@ -4211,75 +4209,75 @@ msgid ""
|
||||
"without libvirt"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:238
|
||||
#: lib/proto.c:240
|
||||
#, c-format
|
||||
msgid ""
|
||||
"check_daemon_socket: read 0x%x from daemon, expected 0x%x. Lost protocol "
|
||||
"synchronization (bad!)\n"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:284
|
||||
#: lib/proto.c:286
|
||||
msgid "xdr_guestfs_message_header failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:293
|
||||
#: lib/proto.c:295
|
||||
msgid "dispatch failed to marshal args"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:387 lib/proto.c:891
|
||||
#: lib/proto.c:389 lib/proto.c:895
|
||||
msgid "operation cancelled by user"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:462
|
||||
#: lib/proto.c:464
|
||||
#, c-format
|
||||
msgid "xdr_guestfs_chunk failed (buf = %p, buflen = %zu)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:560
|
||||
#: lib/proto.c:562
|
||||
#, c-format
|
||||
msgid "received magic signature from guestfsd, but in state %d"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:579
|
||||
#: lib/proto.c:581
|
||||
#, c-format
|
||||
msgid "message length (%u) > maximum possible size (%d)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:847
|
||||
#: lib/proto.c:851
|
||||
msgid "write to daemon socket"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:876
|
||||
#: lib/proto.c:880
|
||||
msgid "receive_file_data: unexpected flag received when reading file chunks"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:884
|
||||
#: lib/proto.c:888
|
||||
msgid "failed to parse file chunk"
|
||||
msgstr ""
|
||||
|
||||
#: lib/proto.c:893
|
||||
#: lib/proto.c:897
|
||||
msgid "file receive cancelled by daemon"
|
||||
msgstr ""
|
||||
|
||||
#: lib/qemu.c:426
|
||||
#: lib/qemu.c:434
|
||||
msgid ""
|
||||
"discard cannot be enabled on this drive: the drive has a read-only overlay"
|
||||
msgstr ""
|
||||
|
||||
#: lib/qemu.c:433
|
||||
#: lib/qemu.c:441
|
||||
msgid ""
|
||||
"discard cannot be enabled on this drive: you have to specify the format of "
|
||||
"the file"
|
||||
msgstr ""
|
||||
|
||||
#: lib/qemu.c:443
|
||||
#: lib/qemu.c:451
|
||||
#, c-format
|
||||
msgid ""
|
||||
"discard cannot be enabled on this drive: qemu does not support discard for "
|
||||
"‘%s’ format files"
|
||||
msgstr ""
|
||||
|
||||
#: lib/qemu.c:463
|
||||
#: lib/qemu.c:471
|
||||
#, c-format
|
||||
msgid ""
|
||||
"discard cannot be enabled on this drive: protocol ‘%s’ does not support "
|
||||
@@ -4299,22 +4297,22 @@ msgstr ""
|
||||
msgid "converting path to absolute path: %s: %s: realpath"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:73 lib/tmpdirs.c:79
|
||||
#: lib/tmpdirs.c:73 lib/tmpdirs.c:80
|
||||
#, c-format
|
||||
msgid "setting temporary directory"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:78
|
||||
#: lib/tmpdirs.c:79
|
||||
#, c-format
|
||||
msgid "%s: %s: ‘%s’ is not a directory"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:195
|
||||
#: lib/tmpdirs.c:197
|
||||
#, c-format
|
||||
msgid "%s: cannot create temporary directory"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:197
|
||||
#: lib/tmpdirs.c:199
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: cannot create temporary directory. It may be that $XDG_RUNTIME_DIR is "
|
||||
@@ -4324,32 +4322,32 @@ msgid ""
|
||||
"creating /run/user/%d with the right ownership."
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:271
|
||||
#: lib/tmpdirs.c:273
|
||||
#, c-format
|
||||
msgid "socket path too long: %s/%s"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:275
|
||||
#: lib/tmpdirs.c:277
|
||||
#, c-format
|
||||
msgid "%s"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:323
|
||||
#: lib/tmpdirs.c:325
|
||||
#, c-format
|
||||
msgid "stat: %s"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:328
|
||||
#: lib/tmpdirs.c:330
|
||||
#, c-format
|
||||
msgid "security: cached appliance %s is not owned by UID %ju"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:334
|
||||
#: lib/tmpdirs.c:336
|
||||
#, c-format
|
||||
msgid "security: cached appliance %s is not a directory (mode %o)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/tmpdirs.c:340
|
||||
#: lib/tmpdirs.c:342
|
||||
#, c-format
|
||||
msgid "security: cached appliance %s is writable by group or other (mode %o)"
|
||||
msgstr ""
|
||||
|
||||
@@ -50,9 +50,7 @@ main (int argc, char *argv[])
|
||||
|
||||
assert (guestfs_set_path (g, NULL) == 0);
|
||||
assert (guestfs_set_append (g, NULL) == 0);
|
||||
#ifdef QEMU
|
||||
assert (guestfs_set_qemu (g, NULL) == 0);
|
||||
#endif
|
||||
|
||||
guestfs_close (g);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
Reference in New Issue
Block a user