[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PULL 07/13] qemu-io: Add generic function for reinitializi
From: |
Max Reitz |
Subject: |
[Qemu-block] [PULL 07/13] qemu-io: Add generic function for reinitializing optind. |
Date: |
Thu, 31 Jan 2019 01:59:39 +0100 |
From: "Richard W.M. Jones" <address@hidden>
On FreeBSD 11.2:
$ nbdkit memory size=1M --run './qemu-io -f raw -c "aio_write 0 512" $nbd'
Parsing error: non-numeric argument, or extraneous/unrecognized suffix --
aio_write
After main option parsing, we reinitialize optind so we can parse each
command. However reinitializing optind to 0 does not work on FreeBSD.
What happens when you do this is optind remains 0 after the option
parsing loop, and the result is we try to parse argv[optind] ==
argv[0] == "aio_write" as if it was the first parameter.
The FreeBSD manual page says:
In order to use getopt() to evaluate multiple sets of arguments, or to
evaluate a single set of arguments multiple times, the variable optreset
must be set to 1 before the second and each additional set of calls to
getopt(), and the variable optind must be reinitialized.
(From the rest of the man page it is clear that optind must be
reinitialized to 1).
The glibc man page says:
A program that scans multiple argument vectors, or rescans the same
vector more than once, and wants to make use of GNU extensions such as
'+' and '-' at the start of optstring, or changes the value of
POSIXLY_CORRECT between scans, must reinitialize getopt() by resetting
optind to 0, rather than the traditional value of 1. (Resetting to 0
forces the invocation of an internal initialization routine that
rechecks POSIXLY_CORRECT and checks for GNU extensions in optstring.)
This commit introduces an OS-portability function called
qemu_reset_optind which provides a way of resetting optind that works
on FreeBSD and platforms that use optreset, while keeping it the same
as now on other platforms.
Note that the qemu codebase sets optind in many other places, but in
those other places it's setting a local variable and not using getopt.
This change is only needed in places where we are using getopt and the
associated global variable optind.
Signed-off-by: Richard W.M. Jones <address@hidden>
Message-id: address@hidden
Reviewed-by: Daniel P. Berrangé <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
Signed-off-by: Max Reitz <address@hidden>
---
configure | 14 ++++++++++++++
include/qemu/osdep.h | 16 ++++++++++++++++
qemu-img.c | 2 +-
qemu-io-cmds.c | 2 +-
4 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index b18281c61f..831d26d4ae 100755
--- a/configure
+++ b/configure
@@ -4269,6 +4269,17 @@ if compile_prog "" "" ; then
signalfd=yes
fi
+# check if optreset global is declared by <getopt.h>
+optreset="no"
+cat > $TMPC << EOF
+#include <getopt.h>
+int main(void) { return optreset; }
+EOF
+
+if compile_prog "" "" ; then
+ optreset=yes
+fi
+
# check if eventfd is supported
eventfd=no
cat > $TMPC << EOF
@@ -6643,6 +6654,9 @@ fi
if test "$signalfd" = "yes" ; then
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
fi
+if test "$optreset" = "yes" ; then
+ echo "HAVE_OPTRESET=y" >> $config_host_mak
+fi
if test "$tcg" = "yes"; then
echo "CONFIG_TCG=y" >> $config_host_mak
if test "$tcg_interpreter" = "yes" ; then
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 80df7253db..840af09cb0 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -109,6 +109,7 @@ extern int daemon(int, int);
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <assert.h>
@@ -604,4 +605,19 @@ extern int qemu_icache_linesize_log;
extern int qemu_dcache_linesize;
extern int qemu_dcache_linesize_log;
+/*
+ * After using getopt or getopt_long, if you need to parse another set
+ * of options, then you must reset optind. Unfortunately the way to
+ * do this varies between implementations of getopt.
+ */
+static inline void qemu_reset_optind(void)
+{
+#ifdef HAVE_OPTRESET
+ optind = 1;
+ optreset = 1;
+#else
+ optind = 0;
+#endif
+}
+
#endif
diff --git a/qemu-img.c b/qemu-img.c
index ad04f59565..25288c4d18 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4962,7 +4962,7 @@ int main(int argc, char **argv)
return 0;
}
argv += optind;
- optind = 0;
+ qemu_reset_optind();
if (!trace_init_backends()) {
exit(1);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 2c39124036..ee8f56e46a 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -114,7 +114,7 @@ static int command(BlockBackend *blk, const cmdinfo_t *ct,
int argc,
}
}
- optind = 0;
+ qemu_reset_optind();
return ct->cfunc(blk, argc, argv);
}
--
2.20.1
- [Qemu-block] [PULL 00/13] Block patches, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 01/13] qapi: add x-debug-query-block-graph, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 02/13] scripts: add render_block_graph function for QEMUMachine, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 03/13] block/ssh: Convert from DPRINTF() macro to trace events, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 04/13] block/curl: Convert from DPRINTF() macro to trace events, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 05/13] block/file-posix: Convert from DPRINTF() macro to trace events, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 07/13] qemu-io: Add generic function for reinitializing optind.,
Max Reitz <=
- [Qemu-block] [PULL 06/13] block/sheepdog: Convert from DPRINTF() macro to trace events, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 08/13] nvme: use TYPE_NVME instead of constant string, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 09/13] nvme: ensure the num_queues is not zero, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 10/13] nvme: use pci_dev directly in nvme_realize, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 11/13] iotests.py: Add qemu_nbd_pipe(), Max Reitz, 2019/01/30
- [Qemu-block] [PULL 13/13] iotests: Allow 147 to be run concurrently, Max Reitz, 2019/01/30
- [Qemu-block] [PULL 12/13] iotests: Bind qemu-nbd to localhost in 147, Max Reitz, 2019/01/30