docs/manpages/virt-qemu-run.rst | 9 +++ src/qemu/qemu_shim.c | 121 +++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-)
Adding a new option --config (or -c) for specifying a custom
qemu.conf file.
Previously, virt-qemu-run loaded default configuration values for
QEMU via qemuStateInitialize(). The configuration was loaded from
a temporary ../etc/ directory using virQEMUDriverConfigLoadFile(),
and any qemu.conf file present in that directory was also loaded
automatically.
This patch allows users to specify a custom configuration file,
which is copied into the temporary directory (or a permanent
folder if the -r option is used) before loading the
configuration. If an existing qemu.conf is present, it is
properly backed up and restored in case of a permanent folder.
The custom qemu.conf is always removed when the program exits.
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/723
Signed-off-by: Adam Julis <ajulis@redhat.com>
---
docs/manpages/virt-qemu-run.rst | 9 +++
src/qemu/qemu_shim.c | 121 +++++++++++++++++++++++++++++++-
2 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/docs/manpages/virt-qemu-run.rst b/docs/manpages/virt-qemu-run.rst
index 4d546ff8cc..ba1c90b52a 100644
--- a/docs/manpages/virt-qemu-run.rst
+++ b/docs/manpages/virt-qemu-run.rst
@@ -72,6 +72,15 @@ whose UUID should match a secret referenced in the guest domain XML.
Display verbose information about startup.
+``-c`` *QEMU-CONF-FILE*,
+``--config``\ =\ *QEMU-CONF-FILE*
+
+Specify the QEMU configuration file to be used for starting the VM.
+*QEMU-CONF-FILE* is the full path to the QEMU configuration file.
+
+If this parameter is omitted, the default configuration values will
+be used.
+
``-h``, ``--help``
Display the command line help.
diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c
index 7fdd69b538..64c87ab264 100644
--- a/src/qemu/qemu_shim.c
+++ b/src/qemu/qemu_shim.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
+#include <fcntl.h>
#include "virfile.h"
#include "virgettext.h"
@@ -132,6 +133,100 @@ qemuShimQuench(void *userData G_GNUC_UNUSED,
{
}
+/* Load specific QEMU config file, is the -c option is used */
+static int
+qemuAddConfigFile(const char *source_file, const char *root, bool *config_to_delete, long long deltams)
+{
+ int ret = -1;
+ struct stat st;
+ VIR_AUTOCLOSE srcFD = -1;
+ VIR_AUTOCLOSE dstFD = -1;
+ g_autofree char *config_dir = NULL;
+ g_autofree char *source_file_real = NULL;
+ g_autofree char *config_path_file = NULL;
+ g_autofree char *config_path_file_real = NULL;
+
+ if ((srcFD = open(source_file, O_RDONLY)) < 0) {
+ g_printerr("Couldn't open specific config file\n");
+ goto cleanup;
+ }
+
+ if (fstat(srcFD, &st) != 0) {
+ g_printerr("Specific config file does not exist\n");
+ goto cleanup;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ g_printerr("Specific config is not a regular file\n");
+ goto cleanup;
+ }
+
+ /* Since source file exists, make the destination path or
+ * validate that it already exists */
+ config_dir = g_strdup_printf("%s/etc/", root);
+
+ if (g_mkdir_with_parents(config_dir, 0777) < 0) {
+ g_printerr("Couldn't make the directory for specific config file\n");
+ goto cleanup;
+ }
+
+ config_path_file = g_strdup_printf("%sqemu.conf", config_dir);
+
+ /* If the source file is same as the destination file, no action needed */
+ if ((source_file_real = realpath(source_file, NULL)) &&
+ (config_path_file_real = realpath(config_path_file, NULL))) {
+ if (STREQ(source_file_real, config_path_file_real)) {
+ ret = 0;
+ goto cleanup;
+ }
+ }
+
+ /* Check already existing qemu.conf in the subfolder, if so, renamed
+ * (appended via deltams constant - should be unique). Final cleanup
+ * at main() will revert this change */
+ if (access(config_path_file, R_OK) == 0) {
+ if (rename(config_path_file, g_strdup_printf("%sqemu_old_%lld.conf",
+ config_dir, deltams)) != 0) {
+ g_printerr("Couldn't rename old config file, try delete it\n");
+ goto cleanup;
+ }
+ }
+
+ if ((dstFD = open(config_path_file, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
+ g_printerr("Couldn't open file for define specific config\n");
+ goto cleanup;
+ }
+
+ /* Set the flag for deleting the new/modified config in main() cleanup,
+ * for ensure that behaviour without the user config will be always
+ * consistent and take default value */
+ *config_to_delete = true;
+
+ do {
+ char buffer[1024];
+ ssize_t readed = 0;
+
+ readed = saferead(srcFD, buffer, 1024);
+
+ if (readed < 0) {
+ g_printerr("Couldn't read from specific config\n");
+ goto cleanup;
+ } else if (readed == 0) {
+ break;
+ } else {
+ ssize_t writed = safewrite(dstFD, buffer, readed);
+ if (writed != readed) {
+ g_printerr("Couldn't write to file for define specific config\n");
+ goto cleanup;
+ }
+ }
+ } while (1);
+
+ ret = 0;
+
+ cleanup:
+ return ret;
+}
+
int main(int argc, char **argv)
{
g_autoptr(virIdentity) sysident = NULL;
@@ -142,8 +237,11 @@ int main(int argc, char **argv)
g_autofree char *uri = NULL;
g_autofree char *suri = NULL;
const char *root = NULL;
+ const char *config = NULL;
+ long long delta_ms = 0;
g_autofree char *escaped = NULL;
bool tmproot = false;
+ bool config_to_delete = false;
int ret = 1;
g_autoptr(GError) error = NULL;
g_auto(GStrv) secrets = NULL;
@@ -156,6 +254,7 @@ int main(int argc, char **argv)
{ "root", 'r', 0, G_OPTION_ARG_STRING, &root, "Root directory", "DIR" },
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Debug output", NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", NULL },
+ { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "Load specific QEMU configuration file", "QEMU-CONF-FILE"},
{ 0 }
};
int quitfd[2] = {-1, -1};
@@ -172,7 +271,7 @@ int main(int argc, char **argv)
return 1;
}
- if (argc != 2) {
+ if (argc != 2 && argc != 3) {
g_autofree char *help = g_option_context_get_help(ctx, TRUE, NULL);
g_printerr("%s", help);
return 1;
@@ -234,6 +333,10 @@ int main(int argc, char **argv)
goto cleanup;
}
+ delta_ms = deltams();
+ if (config && (qemuAddConfigFile(config, root, &config_to_delete, delta_ms) < 0))
+ g_printerr("Specific config file was not loaded, default was used\n");
+
escaped = g_uri_escape_string(root, NULL, true);
virFileActivateDirOverrideForProg(argv[0]);
@@ -402,6 +505,22 @@ int main(int argc, char **argv)
VIR_FORCE_CLOSE(quitfd[0]);
VIR_FORCE_CLOSE(quitfd[1]);
+ if (config_to_delete) {
+ g_autofree char *possible_old_file = g_strdup_printf("%s/etc/qemu_old_%lld.conf",
+ root, delta_ms);
+ g_autofree char *to_delete = g_strdup_printf("%s/etc/qemu.conf", root);
+
+ if (remove(to_delete) != 0)
+ g_printerr("Deleting specific config failed, located in: %s\n",
+ to_delete);
+
+ if (access(possible_old_file, R_OK) == 0) {
+ if (rename(possible_old_file, to_delete) != 0)
+ g_printerr("Renaming your old qemu.conf failed, ups, located in %s\n",
+ possible_old_file);
+ }
+ }
+
if (dom != NULL)
virDomainFree(dom);
if (sconn != NULL)
--
2.47.1
On Tue, Jan 28, 2025 at 03:13:04PM +0100, Adam Julis wrote: > Adding a new option --config (or -c) for specifying a custom > qemu.conf file. > > Previously, virt-qemu-run loaded default configuration values for > QEMU via qemuStateInitialize(). The configuration was loaded from > a temporary ../etc/ directory using virQEMUDriverConfigLoadFile(), > and any qemu.conf file present in that directory was also loaded > automatically. > > This patch allows users to specify a custom configuration file, > which is copied into the temporary directory (or a permanent > folder if the -r option is used) before loading the > configuration. If an existing qemu.conf is present, it is > properly backed up and restored in case of a permanent folder. > The custom qemu.conf is always removed when the program exits. IMHO if the user is passing a '-r' option, then they can already ensure that directory they're pointing to contains a suitable qemu.conf, and we shouldn't try to relpace that. The patch is adding an unreasonable amount of complexity with backups & restore, for the -r case, that just isn't compelling to exist. Similarly it doesn't seem compelling to deep copy the file contents since this is a read-only file. Without that, the whole patch would be little more than two API calls g_mkdir_with_parents() followed by symlink(). With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
On 1/28/25 15:13, Adam Julis wrote:
> Adding a new option --config (or -c) for specifying a custom
> qemu.conf file.
>
> Previously, virt-qemu-run loaded default configuration values for
> QEMU via qemuStateInitialize(). The configuration was loaded from
> a temporary ../etc/ directory using virQEMUDriverConfigLoadFile(),
> and any qemu.conf file present in that directory was also loaded
> automatically.
>
> This patch allows users to specify a custom configuration file,
> which is copied into the temporary directory (or a permanent
> folder if the -r option is used) before loading the
> configuration. If an existing qemu.conf is present, it is
> properly backed up and restored in case of a permanent folder.
> The custom qemu.conf is always removed when the program exits.
>
> Resolves: https://gitlab.com/libvirt/libvirt/-/issues/723
> Signed-off-by: Adam Julis <ajulis@redhat.com>
> ---
> docs/manpages/virt-qemu-run.rst | 9 +++
> src/qemu/qemu_shim.c | 121 +++++++++++++++++++++++++++++++-
> 2 files changed, 129 insertions(+), 1 deletion(-)
>
> diff --git a/docs/manpages/virt-qemu-run.rst b/docs/manpages/virt-qemu-run.rst
> index 4d546ff8cc..ba1c90b52a 100644
> --- a/docs/manpages/virt-qemu-run.rst
> +++ b/docs/manpages/virt-qemu-run.rst
> @@ -72,6 +72,15 @@ whose UUID should match a secret referenced in the guest domain XML.
>
> Display verbose information about startup.
>
> +``-c`` *QEMU-CONF-FILE*,
> +``--config``\ =\ *QEMU-CONF-FILE*
> +
> +Specify the QEMU configuration file to be used for starting the VM.
> +*QEMU-CONF-FILE* is the full path to the QEMU configuration file.
> +
> +If this parameter is omitted, the default configuration values will
> +be used.
> +
> ``-h``, ``--help``
>
> Display the command line help.
> diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c
> index 7fdd69b538..64c87ab264 100644
> --- a/src/qemu/qemu_shim.c
> +++ b/src/qemu/qemu_shim.c
> @@ -23,6 +23,7 @@
> #include <stdio.h>
> #include <stdbool.h>
> #include <unistd.h>
> +#include <fcntl.h>
>
> #include "virfile.h"
> #include "virgettext.h"
> @@ -132,6 +133,100 @@ qemuShimQuench(void *userData G_GNUC_UNUSED,
> {
> }
>
> +/* Load specific QEMU config file, is the -c option is used */
> +static int
> +qemuAddConfigFile(const char *source_file, const char *root, bool *config_to_delete, long long deltams)
One argument per line please.
> +{
> + int ret = -1;
> + struct stat st;
> + VIR_AUTOCLOSE srcFD = -1;
> + VIR_AUTOCLOSE dstFD = -1;
> + g_autofree char *config_dir = NULL;
> + g_autofree char *source_file_real = NULL;
> + g_autofree char *config_path_file = NULL;
> + g_autofree char *config_path_file_real = NULL;
> +
> + if ((srcFD = open(source_file, O_RDONLY)) < 0) {
> + g_printerr("Couldn't open specific config file\n");
> + goto cleanup;
> + }
> +
> + if (fstat(srcFD, &st) != 0) {
> + g_printerr("Specific config file does not exist\n");
> + goto cleanup;
> + }
> + if (!S_ISREG(st.st_mode)) {
> + g_printerr("Specific config is not a regular file\n");
> + goto cleanup;
> + }
> +
> + /* Since source file exists, make the destination path or
> + * validate that it already exists */
> + config_dir = g_strdup_printf("%s/etc/", root);
> +
> + if (g_mkdir_with_parents(config_dir, 0777) < 0) {
> + g_printerr("Couldn't make the directory for specific config file\n");
> + goto cleanup;
> + }
> +
> + config_path_file = g_strdup_printf("%sqemu.conf", config_dir);
> +
> + /* If the source file is same as the destination file, no action needed */
> + if ((source_file_real = realpath(source_file, NULL)) &&
> + (config_path_file_real = realpath(config_path_file, NULL))) {
> + if (STREQ(source_file_real, config_path_file_real)) {
> + ret = 0;
> + goto cleanup;
> + }
> + }
> +
> + /* Check already existing qemu.conf in the subfolder, if so, renamed
> + * (appended via deltams constant - should be unique). Final cleanup
> + * at main() will revert this change */
> + if (access(config_path_file, R_OK) == 0) {
> + if (rename(config_path_file, g_strdup_printf("%sqemu_old_%lld.conf",
> + config_dir, deltams)) != 0) {
Surely this g_strdup_printf() must leak memory.
> + g_printerr("Couldn't rename old config file, try delete it\n");
> + goto cleanup;
> + }
Hm.. this is the point where I'd expect config_to_delete to be set. Just
consider that rename() succeeds, but ...
> + }
> +
> + if ((dstFD = open(config_path_file, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
> + g_printerr("Couldn't open file for define specific config\n");
> + goto cleanup;
> + }
... open() fails. Then, when caller is doing cleanup it needs to rename
the file back. This renders the variable name a bit misleading though,
how about 'rename_config'?
> +
> + /* Set the flag for deleting the new/modified config in main() cleanup,
> + * for ensure that behaviour without the user config will be always
> + * consistent and take default value */
> + *config_to_delete = true;
> +
> + do {
> + char buffer[1024];
> + ssize_t readed = 0;
Inventive naming :-) Typically we use nread.
> +
> + readed = saferead(srcFD, buffer, 1024);
> +
> + if (readed < 0) {
> + g_printerr("Couldn't read from specific config\n");
> + goto cleanup;
> + } else if (readed == 0) {
> + break;
> + } else {
> + ssize_t writed = safewrite(dstFD, buffer, readed);
> + if (writed != readed) {
> + g_printerr("Couldn't write to file for define specific config\n");
> + goto cleanup;
> + }
> + }
> + } while (1);
> +
> + ret = 0;
> +
> + cleanup:
> + return ret;
This is pretty useless label. s/goto cleanup/return -1/ (except for a
few places where ret is set to 0 before jumping).
> +}
> +
> int main(int argc, char **argv)
> {
> g_autoptr(virIdentity) sysident = NULL;
> @@ -142,8 +237,11 @@ int main(int argc, char **argv)
> g_autofree char *uri = NULL;
> g_autofree char *suri = NULL;
> const char *root = NULL;
> + const char *config = NULL;
> + long long delta_ms = 0;
> g_autofree char *escaped = NULL;
> bool tmproot = false;
> + bool config_to_delete = false;
> int ret = 1;
> g_autoptr(GError) error = NULL;
> g_auto(GStrv) secrets = NULL;
> @@ -156,6 +254,7 @@ int main(int argc, char **argv)
> { "root", 'r', 0, G_OPTION_ARG_STRING, &root, "Root directory", "DIR" },
> { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Debug output", NULL },
> { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", NULL },
> + { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "Load specific QEMU configuration file", "QEMU-CONF-FILE"},
> { 0 }
> };
> int quitfd[2] = {-1, -1};
> @@ -172,7 +271,7 @@ int main(int argc, char **argv)
> return 1;
> }
>
> - if (argc != 2) {
> + if (argc != 2 && argc != 3) {
> g_autofree char *help = g_option_context_get_help(ctx, TRUE, NULL);
> g_printerr("%s", help);
> return 1;
> @@ -234,6 +333,10 @@ int main(int argc, char **argv)
> goto cleanup;
> }
>
> + delta_ms = deltams();
> + if (config && (qemuAddConfigFile(config, root, &config_to_delete, delta_ms) < 0))
> + g_printerr("Specific config file was not loaded, default was used\n");
Surely this has to be a reason to stop execution and let user fix things.
> +
> escaped = g_uri_escape_string(root, NULL, true);
>
> virFileActivateDirOverrideForProg(argv[0]);
> @@ -402,6 +505,22 @@ int main(int argc, char **argv)
> VIR_FORCE_CLOSE(quitfd[0]);
> VIR_FORCE_CLOSE(quitfd[1]);
>
> + if (config_to_delete) {
> + g_autofree char *possible_old_file = g_strdup_printf("%s/etc/qemu_old_%lld.conf",
> + root, delta_ms);
> + g_autofree char *to_delete = g_strdup_printf("%s/etc/qemu.conf", root);
> +
> + if (remove(to_delete) != 0)
> + g_printerr("Deleting specific config failed, located in: %s\n",
> + to_delete);
> +
> + if (access(possible_old_file, R_OK) == 0) {
> + if (rename(possible_old_file, to_delete) != 0)
> + g_printerr("Renaming your old qemu.conf failed, ups, located in %s\n",
> + possible_old_file);
> + }
This can made better. Firstly - you can avoid reconstruting path again
by simply returning it from qemuAddConfigFile() [1]. Secondly - the way
that 'possible_old_file' is reconstructed is very fragile - what if
somebody modifies delta_ms? Thirdly - you do not need to remove() the
file - just renmae(possible_old_file, to_delete).
1: In fact, to my previous point about 'config_to_delete' rename -
qemuAddConfigFile() can simply set a pointer which would be then used as
a signal to rename the file.
Something like this:
int main() {
/* this would effectively be $root/etc/qemu.conf */
g_autofree char *old_config_file = NULL;
/* this would be $root/etc/qemu_old_XXXX.conf */
g_autofree char *saved_config_file = NULL;
...
qemuAddConfigFile(config, root, &old_config_file, &saved_config_file);
...
cleanup:
...
if (saved_config_file &&
rename(saved_config_file, old_config_file) < 0) {
g_printerr();
}
...
}
Michal
Adding a new option --config (or -c) for specifying a custom
qemu.conf file.
Previously, virt-qemu-run loaded default configuration values for
QEMU via qemuStateInitialize(). The configuration was loaded from
a temporary ../etc/ directory using virQEMUDriverConfigLoadFile(),
and any qemu.conf file present in that directory was also loaded
automatically.
This patch allows users to specify a custom configuration file,
which is copied into the temporary directory (or a permanent
folder if the -r option is used) before loading the
configuration. If an existing qemu.conf is present, it is
properly backed up and restored in case of a permanent folder.
The custom qemu.conf is always removed when the program exits.
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/723
Signed-off-by: Adam Julis <ajulis@redhat.com>
---
Changes to v1:
- formatting
- g_strdup
- deleted redundant variables, cleanup
- naming
- error in loading function caused interrupting of program
docs/manpages/virt-qemu-run.rst | 9 +++
src/qemu/qemu_shim.c | 120 +++++++++++++++++++++++++++++++-
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/docs/manpages/virt-qemu-run.rst b/docs/manpages/virt-qemu-run.rst
index 4d546ff8cc..ba1c90b52a 100644
--- a/docs/manpages/virt-qemu-run.rst
+++ b/docs/manpages/virt-qemu-run.rst
@@ -72,6 +72,15 @@ whose UUID should match a secret referenced in the guest domain XML.
Display verbose information about startup.
+``-c`` *QEMU-CONF-FILE*,
+``--config``\ =\ *QEMU-CONF-FILE*
+
+Specify the QEMU configuration file to be used for starting the VM.
+*QEMU-CONF-FILE* is the full path to the QEMU configuration file.
+
+If this parameter is omitted, the default configuration values will
+be used.
+
``-h``, ``--help``
Display the command line help.
diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c
index 7fdd69b538..9672b85183 100644
--- a/src/qemu/qemu_shim.c
+++ b/src/qemu/qemu_shim.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
+#include <fcntl.h>
#include "virfile.h"
#include "virgettext.h"
@@ -132,6 +133,101 @@ qemuShimQuench(void *userData G_GNUC_UNUSED,
{
}
+/* Load specific QEMU config file for the -c option */
+static int
+qemuAddConfigFile(const char *source_file,
+ const char *root,
+ char **old_config_file,
+ char **saved_config_file,
+ long long deltams)
+{
+ struct stat st;
+ VIR_AUTOCLOSE srcFD = -1;
+ VIR_AUTOCLOSE dstFD = -1;
+ g_autofree char *config_dir = NULL;
+ g_autofree char *config_dir_file = NULL;
+ g_autofree char *config_dir_file_real = NULL;
+ g_autofree char *source_file_real = NULL;
+
+ if (source_file == NULL)
+ return 0;
+
+ if ((srcFD = open(source_file, O_RDONLY)) < 0) {
+ g_printerr("Couldn't open specific config file\n");
+ return -1;
+ }
+
+ if (fstat(srcFD, &st) != 0) {
+ g_printerr("Specific config file does not exist\n");
+ return -1;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ g_printerr("Specific config is not a regular file\n");
+ return -1;
+ }
+
+ /* Since source file exists, make the destination path or
+ * validate that it already exists */
+ config_dir = g_strdup_printf("%s/etc/", root);
+
+ if (g_mkdir_with_parents(config_dir, 0777) < 0) {
+ g_printerr("Couldn't make the directory for specific config file\n");
+ return -1;
+ }
+
+ config_dir_file = g_strdup_printf("%sqemu.conf", config_dir);
+
+ /* If the source file is same as the destination file, no action needed */
+ if ((source_file_real = realpath(source_file, NULL)) &&
+ (config_dir_file_real = realpath(config_dir_file, NULL))) {
+ if (STREQ(source_file_real, config_dir_file_real)) {
+ return 0;
+ }
+ }
+
+ /* Check already existing qemu.conf in the subfolder, if so, renamed
+ * (appended via deltams constant - should be unique). Final cleanup
+ * at main() will revert this change */
+ if (access(config_dir_file, R_OK) == 0) {
+ *old_config_file = g_strdup_printf("%sqemu_old_%lld.conf",
+ config_dir, deltams);
+
+ if (rename(config_dir_file, *old_config_file) != 0) {
+ g_printerr("Couldn't rename old config file, try delete it\n");
+ return -1;
+ }
+ }
+
+ if ((dstFD = open(config_dir_file, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
+ g_printerr("Couldn't open file for define specific config\n");
+ return -1;
+ }
+
+ *saved_config_file = g_steal_pointer(&config_dir_file);
+
+ do {
+ char buffer[1024];
+ ssize_t nread = 0;
+
+ nread = saferead(srcFD, buffer, 1024);
+
+ if (nread < 0) {
+ g_printerr("Couldn't read from specific config\n");
+ return -1;
+ } else if (nread == 0) {
+ break;
+ } else {
+ ssize_t nwrite = safewrite(dstFD, buffer, nread);
+ if (nwrite != nread) {
+ g_printerr("Couldn't write to file for define specific config\n");
+ return -1;
+ }
+ }
+ } while (1);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
g_autoptr(virIdentity) sysident = NULL;
@@ -141,7 +237,10 @@ int main(int argc, char **argv)
g_autofree char *xml = NULL;
g_autofree char *uri = NULL;
g_autofree char *suri = NULL;
+ g_autofree char *old_config_file = NULL;
+ g_autofree char *saved_config_file = NULL;
const char *root = NULL;
+ const char *config = NULL;
g_autofree char *escaped = NULL;
bool tmproot = false;
int ret = 1;
@@ -156,6 +255,7 @@ int main(int argc, char **argv)
{ "root", 'r', 0, G_OPTION_ARG_STRING, &root, "Root directory", "DIR" },
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Debug output", NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", NULL },
+ { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "Load specific QEMU configuration file", "QEMU-CONF-FILE"},
{ 0 }
};
int quitfd[2] = {-1, -1};
@@ -172,7 +272,7 @@ int main(int argc, char **argv)
return 1;
}
- if (argc != 2) {
+ if (argc != 2 && argc != 3) {
g_autofree char *help = g_option_context_get_help(ctx, TRUE, NULL);
g_printerr("%s", help);
return 1;
@@ -234,6 +334,12 @@ int main(int argc, char **argv)
goto cleanup;
}
+ if (config && qemuAddConfigFile(config, root, &old_config_file,
+ &saved_config_file, deltams()) < 0) {
+ g_printerr("Specific config file was not loaded, process interupted\n");
+ goto cleanup;
+ }
+
escaped = g_uri_escape_string(root, NULL, true);
virFileActivateDirOverrideForProg(argv[0]);
@@ -402,6 +508,18 @@ int main(int argc, char **argv)
VIR_FORCE_CLOSE(quitfd[0]);
VIR_FORCE_CLOSE(quitfd[1]);
+ if (saved_config_file) {
+ if (remove(saved_config_file) != 0)
+ g_printerr("Deleting specific config failed, located in: %s\n",
+ saved_config_file);
+
+ if (old_config_file && access(old_config_file, R_OK) == 0) {
+ if (rename(old_config_file, saved_config_file) != 0)
+ g_printerr("Renaming your old qemu.conf failed, ups, located in %s\n",
+ old_config_file);
+ }
+ }
+
if (dom != NULL)
virDomainFree(dom);
if (sconn != NULL)
--
2.47.1
© 2016 - 2026 Red Hat, Inc.