[libvirt PATCH v2 00/13] even less gnulib: 25 more modules purged, leaving 25 to go

A continued effort to purge gnulib from the libvirt build system. The bulk of the win comes from implementing our own Winsock portability wrappers. The use of GSocket turned out to have many complications, making it hard for us to achieve the same level of functionality as we currently have. Thus we take a simpler wrapping approach that GNULIB does for Winsock too. Changed in v2: - Don't import intprops.h, use replacement macros instead - Various fixes to windows socket portability patch and actually verify virsh works - Simplify some ifdef checks to use WIN32 instead of a more complex conditional Daniel P. Berrangé (13): src: replace use of INT_BUFSIZE_BOUND macros src: remove use of the INT_MULTIPLY_OVERFLOW macro tests: always declare environ build: validate headers against local gnulib not git repo util: add detection of openpty function util: introduce compat wrappers for Winsock2 src: convert code to use new socket portability wrappers util: pull gnulib physmem impl into local code util: replace atomic ops impls with g_atomic_int* src: replace verify(expr) with G_STATIC_ASSERT(expr) src: conditionally exclude cfmakeraw/termios.h on WIN32 src: replace gmtime_r/localtime_r/strftime with GDateTime bootstrap: remove 25 more gnulib modules bootstrap.conf | 50 --- build-aux/syntax-check.mk | 29 +- configure.ac | 5 +- examples/c/misc/event-test.c | 12 +- m4/virt-manywarnings.m4 | 339 ++++++++++++++++++++ m4/virt-warnings.m4 | 115 +++++++ src/conf/capabilities.c | 1 - src/conf/domain_conf.c | 11 +- src/conf/snapshot_conf.h | 2 +- src/conf/virdomaincheckpointobjlist.c | 8 +- src/esx/esx_network_driver.c | 2 +- src/esx/esx_storage_backend_iscsi.c | 2 +- src/esx/esx_storage_backend_vmfs.c | 2 +- src/hyperv/hyperv_driver.c | 3 +- src/internal.h | 3 +- src/libvirt-domain.c | 6 +- src/libxl/libxl_domain.c | 12 +- src/libxl/libxl_driver.c | 2 +- src/libxl/xen_xm.c | 3 +- src/lxc/lxc_process.c | 4 +- src/nwfilter/nwfilter_dhcpsnoop.c | 10 +- src/nwfilter/nwfilter_ebiptables_driver.c | 35 +- src/nwfilter/nwfilter_learnipaddr.c | 14 +- src/qemu/qemu_blockjob.h | 4 +- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_command.c | 17 +- src/qemu/qemu_driver.c | 12 +- src/qemu/qemu_firmware.h | 2 +- src/qemu/qemu_migration_params.c | 2 +- src/qemu/qemu_process.c | 4 +- src/remote/remote_daemon_dispatch.c | 15 +- src/remote/remote_driver.c | 5 +- src/rpc/virnetsocket.c | 34 +- src/util/Makefile.inc.am | 3 + src/util/virarch.c | 3 +- src/util/viratomic.h | 351 +------------------- src/util/vircgroup.h | 2 +- src/util/vircrypto.c | 2 +- src/util/virenum.h | 8 +- src/util/virfdstream.c | 10 +- src/util/virfile.c | 25 +- src/util/virhostcpu.c | 4 +- src/util/virhostmem.c | 182 +++++++++-- src/util/virinitctl.c | 4 +- src/util/virkeycode.c | 22 +- src/util/virlog.c | 3 +- src/util/virmacaddr.h | 2 +- src/util/virnetdevbridge.c | 10 +- src/util/virobject.h | 8 +- src/util/virperf.c | 2 +- src/util/virpidfile.c | 7 +- src/util/virportallocator.c | 8 +- src/util/virprocess.c | 2 +- src/util/virsocket.c | 369 ++++++++++++++++++++++ src/util/virsocket.h | 92 ++++++ src/util/virstoragefile.c | 4 +- src/util/virstring.h | 2 + src/util/virtime.c | 35 +- src/util/virtypedparam.h | 2 +- src/util/virutil.c | 33 +- src/vz/vz_driver.c | 2 +- tests/commandhelper.c | 3 + tests/commandtest.c | 3 + tests/qemuxml2argvmock.c | 12 +- tests/viratomictest.c | 2 +- tests/virstringtest.c | 7 +- tests/virsystemdtest.c | 5 +- tests/virtimetest.c | 39 ++- tools/virsh-checkpoint.c | 20 +- tools/virsh-domain-monitor.c | 17 +- tools/virsh-domain.c | 15 +- tools/virsh-network.c | 13 +- tools/virsh-nodedev.c | 2 +- tools/virsh-pool.c | 2 +- tools/virsh-secret.c | 2 +- tools/virsh-snapshot.c | 19 +- tools/virsh.h | 1 - tools/virt-admin.c | 55 +--- tools/virt-host-validate-common.c | 4 +- tools/virt-login-shell.c | 7 +- tools/vsh.c | 31 +- tools/vsh.h | 4 +- 82 files changed, 1400 insertions(+), 827 deletions(-) create mode 100644 m4/virt-manywarnings.m4 create mode 100644 m4/virt-warnings.m4 create mode 100644 src/util/virsocket.c create mode 100644 src/util/virsocket.h -- 2.24.1

Introduce a vastly simpler VIR_INT64_STR_BUFLEN constant which is large enough for all cases where we currently use INT_BUFSIZE_BOUND. This eliminates most use of the gnulib intprops.h header. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/hyperv/hyperv_driver.c | 3 +- src/nwfilter/nwfilter_ebiptables_driver.c | 35 +++++++++-------------- src/nwfilter/nwfilter_learnipaddr.c | 14 ++++----- src/util/virfile.c | 9 +++--- src/util/virhostcpu.c | 3 +- src/util/virlog.c | 3 +- src/util/virnetdevbridge.c | 10 +++---- src/util/virpidfile.c | 7 ++--- src/util/virstring.h | 2 ++ tests/virsystemdtest.c | 5 ++-- tools/virsh-domain-monitor.c | 3 +- tools/virt-login-shell.c | 7 +++-- 12 files changed, 42 insertions(+), 59 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index c9d22ec7c4..4677a25ff8 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -36,7 +36,6 @@ #include "openwsman.h" #include "virstring.h" #include "virkeycode.h" -#include "intprops.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -1339,7 +1338,7 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, Msvm_Keyboard *keyboard = NULL; virBuffer query = VIR_BUFFER_INITIALIZER; hypervInvokeParamsListPtr params = NULL; - char keycodeStr[INT_BUFSIZE_BOUND(int)]; + char keycodeStr[VIR_INT64_STR_BUFLEN]; virCheckFlags(0, -1); diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index eec1414023..f4c192aebb 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -40,7 +40,6 @@ #include "virfile.h" #include "vircommand.h" #include "configmake.h" -#include "intprops.h" #include "virstring.h" #include "virfirewall.h" @@ -820,10 +819,9 @@ iptablesHandleIPHdr(virFirewallPtr fw, bool directionIn, bool *skipRule, bool *skipMatch) { - char ipaddr[INET6_ADDRSTRLEN], - ipaddralt[INET6_ADDRSTRLEN], - number[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))]; + char ipaddr[INET6_ADDRSTRLEN]; + char ipaddralt[INET6_ADDRSTRLEN]; + char number[VIR_INT64_STR_BUFLEN]; const char *src = "--source"; const char *dst = "--destination"; const char *srcrange = "--src-range"; @@ -968,8 +966,7 @@ iptablesHandleIPHdrAfterStateMatch(virFirewallPtr fw, ipHdrDataDefPtr ipHdr, bool directionIn) { - char number[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))]; + char number[VIR_INT64_STR_BUFLEN]; char str[MAX_IPSET_NAME_LENGTH]; if (HAS_ENTRY_ITEM(&ipHdr->dataIPSet) && @@ -1152,10 +1149,8 @@ _iptablesCreateRuleInstance(virFirewallPtr fw, bool maySkipICMP) { char chain[MAX_CHAINNAME_LENGTH]; - char number[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))]; - char numberalt[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))]; + char number[VIR_INT64_STR_BUFLEN]; + char numberalt[VIR_INT64_STR_BUFLEN]; const char *target; bool srcMacSkipped = false; bool skipRule = false; @@ -1789,16 +1784,14 @@ ebtablesCreateRuleInstance(virFirewallPtr fw, virNWFilterVarCombIterPtr vars, bool reverse) { - char macaddr[VIR_MAC_STRING_BUFLEN], - ipaddr[INET_ADDRSTRLEN], - ipmask[INET_ADDRSTRLEN], - ipv6addr[INET6_ADDRSTRLEN], - number[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))], - numberalt[MAX(INT_BUFSIZE_BOUND(uint32_t), - INT_BUFSIZE_BOUND(int))], - field[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)], - fieldalt[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)]; + char macaddr[VIR_MAC_STRING_BUFLEN]; + char ipaddr[INET_ADDRSTRLEN]; + char ipmask[INET_ADDRSTRLEN]; + char ipv6addr[INET6_ADDRSTRLEN]; + char number[VIR_INT64_STR_BUFLEN]; + char numberalt[VIR_INT64_STR_BUFLEN]; + char field[VIR_INT64_STR_BUFLEN]; + char fieldalt[VIR_INT64_STR_BUFLEN]; char chain[MAX_CHAINNAME_LENGTH]; const char *target; bool hasMask = false; diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 46ef65401c..5791724cf4 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -39,7 +39,6 @@ #include "internal.h" -#include "intprops.h" #include "virbuffer.h" #include "viralloc.h" #include "virlog.h" @@ -59,10 +58,6 @@ VIR_LOG_INIT("nwfilter.nwfilter_learnipaddr"); -#define IFINDEX2STR(VARNAME, ifindex) \ - char VARNAME[INT_BUFSIZE_BOUND(ifindex)]; \ - g_snprintf(VARNAME, sizeof(VARNAME), "%d", ifindex); - #define PKT_TIMEOUT_MS 500 /* ms */ /* structure of an ARP request/reply message */ @@ -239,7 +234,7 @@ static int virNWFilterRegisterLearnReq(virNWFilterIPAddrLearnReqPtr req) { int res = -1; - IFINDEX2STR(ifindex_str, req->ifindex); + g_autofree char *ifindex_str = g_strdup_printf("%d", req->ifindex); virMutexLock(&pendingLearnReqLock); @@ -260,6 +255,7 @@ virNWFilterTerminateLearnReq(const char *ifname) int rc = -1; int ifindex; virNWFilterIPAddrLearnReqPtr req; + g_autofree char *ifindex_str = NULL; /* It's possible that it's already been removed as a result of * virNWFilterDeregisterLearnReq during learnIPAddressThread() exit @@ -274,7 +270,7 @@ virNWFilterTerminateLearnReq(const char *ifname) return rc; } - IFINDEX2STR(ifindex_str, ifindex); + ifindex_str = g_strdup_printf("%d", ifindex); virMutexLock(&pendingLearnReqLock); @@ -294,7 +290,7 @@ bool virNWFilterHasLearnReq(int ifindex) { void *res; - IFINDEX2STR(ifindex_str, ifindex); + g_autofree char *ifindex_str = g_strdup_printf("%d", ifindex); virMutexLock(&pendingLearnReqLock); @@ -319,7 +315,7 @@ static virNWFilterIPAddrLearnReqPtr virNWFilterDeregisterLearnReq(int ifindex) { virNWFilterIPAddrLearnReqPtr res; - IFINDEX2STR(ifindex_str, ifindex); + g_autofree char *ifindex_str = g_strdup_printf("%d", ifindex); virMutexLock(&pendingLearnReqLock); diff --git a/src/util/virfile.c b/src/util/virfile.c index 5acac85bb9..6eaabf5371 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -68,7 +68,6 @@ #endif #include "configmake.h" -#include "intprops.h" #include "viralloc.h" #include "vircommand.h" #include "virerror.h" @@ -4067,7 +4066,7 @@ virFileReadValueInt(int *value, const char *format, ...) if (!virFileExists(path)) return -2; - if (virFileReadAll(path, INT_BUFSIZE_BOUND(*value), &str) < 0) + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &str) < 0) return -1; virStringTrimOptionalNewline(str); @@ -4107,7 +4106,7 @@ virFileReadValueUint(unsigned int *value, const char *format, ...) if (!virFileExists(path)) return -2; - if (virFileReadAll(path, INT_BUFSIZE_BOUND(*value), &str) < 0) + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &str) < 0) return -1; virStringTrimOptionalNewline(str); @@ -4147,7 +4146,7 @@ virFileReadValueUllong(unsigned long long *value, const char *format, ...) if (!virFileExists(path)) return -2; - if (virFileReadAll(path, INT_BUFSIZE_BOUND(*value), &str) < 0) + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &str) < 0) return -1; virStringTrimOptionalNewline(str); @@ -4188,7 +4187,7 @@ virFileReadValueScaledInt(unsigned long long *value, const char *format, ...) if (!virFileExists(path)) return -2; - if (virFileReadAll(path, INT_BUFSIZE_BOUND(*value), &str) < 0) + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &str) < 0) return -1; virStringTrimOptionalNewline(str); diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index 7f14340f49..f3adc1b4ae 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -43,7 +43,6 @@ #include "virhostcpupriv.h" #include "physmem.h" #include "virerror.h" -#include "intprops.h" #include "virarch.h" #include "virfile.h" #include "virtypedparam.h" @@ -775,7 +774,7 @@ virHostCPUGetStatsLinux(FILE *procstat, char line[1024]; unsigned long long usr, ni, sys, idle, iowait; unsigned long long irq, softirq, steal, guest, guest_nice; - char cpu_header[4 + INT_BUFSIZE_BOUND(cpuNum)]; + char cpu_header[4 + VIR_INT64_STR_BUFLEN]; if ((*nparams) == 0) { /* Current number of cpu stats supported by linux */ diff --git a/src/util/virlog.c b/src/util/virlog.c index 8a9fb34161..ddc3ac1edb 100644 --- a/src/util/virlog.c +++ b/src/util/virlog.c @@ -45,7 +45,6 @@ #include "virthread.h" #include "virfile.h" #include "virtime.h" -#include "intprops.h" #include "virstring.h" #include "configmake.h" @@ -832,7 +831,7 @@ virLogNewOutputToSyslog(virLogPriority priority, # define IOVEC_SET_STRING(iov, str) IOVEC_SET(iov, str, strlen(str)) /* Used for conversion of numbers to strings, and for length of binary data */ -# define JOURNAL_BUF_SIZE (MAX(INT_BUFSIZE_BOUND(int), sizeof(uint64_t))) +# define JOURNAL_BUF_SIZE (MAX(VIR_INT64_STR_BUFLEN, sizeof(uint64_t))) struct journalState { diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c index 3a7a6dc730..a37bcb4004 100644 --- a/src/util/virnetdevbridge.c +++ b/src/util/virnetdevbridge.c @@ -25,7 +25,6 @@ #include "virfile.h" #include "viralloc.h" #include "virlog.h" -#include "intprops.h" #include "virstring.h" #include <sys/ioctl.h> @@ -125,8 +124,7 @@ static int virNetDevBridgeSet(const char *brname, path = g_strdup_printf(SYSFS_NET_DIR "%s/bridge/%s", brname, paramname); if (virFileExists(path)) { - char valuestr[INT_BUFSIZE_BOUND(value)]; - g_snprintf(valuestr, sizeof(valuestr), "%lu", value); + g_autofree char *valuestr = g_strdup_printf("%lu", value); if (virFileWriteStr(path, valuestr, 0) >= 0) return 0; VIR_DEBUG("Unable to set bridge %s %s via sysfs", brname, paramname); @@ -169,7 +167,7 @@ static int virNetDevBridgeGet(const char *brname, if (virFileExists(path)) { g_autofree char *valuestr = NULL; - if (virFileReadAll(path, INT_BUFSIZE_BOUND(unsigned long), + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &valuestr) < 0) return -1; @@ -215,7 +213,7 @@ virNetDevBridgePortSet(const char *brname, const char *paramname, unsigned long value) { - char valuestr[INT_BUFSIZE_BOUND(value)]; + char valuestr[VIR_INT64_STR_BUFLEN]; int ret = -1; g_autofree char *path = NULL; @@ -251,7 +249,7 @@ virNetDevBridgePortGet(const char *brname, path = g_strdup_printf(SYSFS_NET_DIR "%s/brif/%s/%s", brname, ifname, paramname); - if (virFileReadAll(path, INT_BUFSIZE_BOUND(unsigned long), &valuestr) < 0) + if (virFileReadAll(path, VIR_INT64_STR_BUFLEN, &valuestr) < 0) return -1; if (virStrToLong_ul(valuestr, NULL, 10, value) < 0) { diff --git a/src/util/virpidfile.c b/src/util/virpidfile.c index b08e0d8d52..a8a743504d 100644 --- a/src/util/virpidfile.c +++ b/src/util/virpidfile.c @@ -31,7 +31,6 @@ #include "virfile.h" #include "viralloc.h" #include "virutil.h" -#include "intprops.h" #include "virlog.h" #include "virerror.h" #include "virstring.h" @@ -57,7 +56,7 @@ int virPidFileWritePath(const char *pidfile, { int rc; int fd; - char pidstr[INT_BUFSIZE_BOUND(pid)]; + char pidstr[VIR_INT64_STR_BUFLEN]; if ((fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, @@ -110,7 +109,7 @@ int virPidFileReadPath(const char *path, int rc; ssize_t bytes; long long pid_value = 0; - char pidstr[INT_BUFSIZE_BOUND(pid_value)]; + char pidstr[VIR_INT64_STR_BUFLEN]; char *endptr = NULL; *pid = 0; @@ -333,7 +332,7 @@ int virPidFileAcquirePath(const char *path, pid_t pid) { int fd = -1; - char pidstr[INT_BUFSIZE_BOUND(pid)]; + char pidstr[VIR_INT64_STR_BUFLEN]; if (path[0] == '\0') return 0; diff --git a/src/util/virstring.h b/src/util/virstring.h index a2cd92cf83..360c68395c 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -22,6 +22,8 @@ #include "internal.h" +#define VIR_INT64_STR_BUFLEN 21 + char **virStringSplitCount(const char *string, const char *delim, size_t max_tokens, diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c index 26876850b8..a9b02af7db 100644 --- a/tests/virsystemdtest.c +++ b/tests/virsystemdtest.c @@ -33,7 +33,6 @@ # include "virlog.h" # include "virmock.h" # include "rpc/virnetsocket.h" -# include "intprops.h" # define VIR_FROM_THIS VIR_FROM_NONE VIR_LOG_INIT("tests.systemdtest"); @@ -548,8 +547,8 @@ testActivation(bool useNames) size_t nsockIP; int ret = -1; size_t i; - char nfdstr[INT_BUFSIZE_BOUND(size_t)]; - char pidstr[INT_BUFSIZE_BOUND(pid_t)]; + char nfdstr[VIR_INT64_STR_BUFLEN]; + char pidstr[VIR_INT64_STR_BUFLEN]; virSystemdActivationMap map[2]; int *fds = NULL; size_t nfds = 0; diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index e357635757..efcdc613c6 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -29,7 +29,6 @@ #include "internal.h" #include "conf/virdomainobjlist.h" -#include "intprops.h" #include "viralloc.h" #include "virmacaddr.h" #include "virxml.h" @@ -1964,7 +1963,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd) bool ret = false; virshDomainListPtr list = NULL; virDomainPtr dom; - char id_buf[INT_BUFSIZE_BOUND(unsigned int)]; + char id_buf[VIR_INT64_STR_BUFLEN]; unsigned int id; unsigned int flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE; vshTablePtr table = NULL; diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c index 7d1e0ccc8a..cf4a249f0a 100644 --- a/tools/virt-login-shell.c +++ b/tools/virt-login-shell.c @@ -33,11 +33,12 @@ * so don't introduce a link time dep, which we must avoid */ #include "gnulib/lib/configmake.h" -#include "gnulib/lib/intprops.h" + +#define VIR_INT64_STR_BUFLEN 21 int main(int argc, char **argv) { - char uidstr[INT_BUFSIZE_BOUND(uid_t)]; - char gidstr[INT_BUFSIZE_BOUND(gid_t)]; + char uidstr[VIR_INT64_STR_BUFLEN]; + char gidstr[VIR_INT64_STR_BUFLEN]; const char * newargv[6]; size_t nargs = 0; char *newenv[] = { -- 2.24.1

On Thu, Jan 16, 2020 at 03:24:36PM +0000, Daniel P. Berrangé wrote:
Introduce a vastly simpler VIR_INT64_STR_BUFLEN constant which is large enough for all cases where we currently use INT_BUFSIZE_BOUND. This eliminates most use of the gnulib intprops.h header.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/hyperv/hyperv_driver.c | 3 +- src/nwfilter/nwfilter_ebiptables_driver.c | 35 +++++++++-------------- src/nwfilter/nwfilter_learnipaddr.c | 14 ++++----- src/util/virfile.c | 9 +++--- src/util/virhostcpu.c | 3 +- src/util/virlog.c | 3 +- src/util/virnetdevbridge.c | 10 +++---- src/util/virpidfile.c | 7 ++--- src/util/virstring.h | 2 ++ tests/virsystemdtest.c | 5 ++-- tools/virsh-domain-monitor.c | 3 +- tools/virt-login-shell.c | 7 +++-- 12 files changed, 42 insertions(+), 59 deletions(-)
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>

The GLib g_size_checked_mul() function is not quite the same signature, and gives compiler warnings due to not correctly casting from gsize to guint64/32. Implementing a replacement for INT_MULTIPLY_OVERFLOW is easy enough to do ourselves. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 15 --------------- src/internal.h | 2 ++ src/libvirt-domain.c | 6 ++---- src/remote/remote_daemon_dispatch.c | 5 ++--- src/remote/remote_driver.c | 5 ++--- 5 files changed, 8 insertions(+), 25 deletions(-) diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 7e7c59c3df..6e9328ee63 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -1606,20 +1606,6 @@ sc_prohibit_strings_without_use: re='\<(strn?casecmp|ffs(ll)?)\>' \ $(_sc_header_without_use) -# Extract the raw list of symbol names with this: -gl_extract_define_simple = \ - /^\# *define ([A-Z]\w+)\(/ and print $$1 -# Filter out duplicates and convert to a space-separated list: -_intprops_names = \ - $(shell f=$(gnulib_dir)/lib/intprops.h; \ - perl -lne '$(gl_extract_define_simple)' $$f | sort -u | tr '\n' ' ') -# Remove trailing space and convert to a regular expression: -_intprops_syms_re = $(subst $(_sp),|,$(strip $(_intprops_names))) -# Prohibit the inclusion of intprops.h without an actual use. -sc_prohibit_intprops_without_use: - @h='intprops.h' \ - re='\<($(_intprops_syms_re)) *\(' \ - $(_sc_header_without_use) _stddef_syms_re = NULL|offsetof|ptrdiff_t|size_t|wchar_t # Prohibit the inclusion of stddef.h without an actual use. @@ -1714,7 +1700,6 @@ sc_prohibit_defined_have_decl_tests: # ================================================================== gl_other_headers_ ?= \ - intprops.h \ openat.h \ stat-macros.h diff --git a/src/internal.h b/src/internal.h index 686b7cfcc2..e356db6c78 100644 --- a/src/internal.h +++ b/src/internal.h @@ -38,6 +38,8 @@ # define sa_assert(expr) /* empty */ #endif +#define VIR_INT_MULTIPLY_OVERFLOW(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXINT / (b))) + /* The library itself is allowed to use deprecated functions / * variables, so effectively undefine the deprecated attribute * which would otherwise be defined in libvirt.h. diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d0304e174f..e7585d1872 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -21,8 +21,6 @@ #include <config.h> #include <sys/stat.h> -#include "intprops.h" - #include "datatypes.h" #include "viralloc.h" #include "virfile.h" @@ -7302,7 +7300,7 @@ virDomainGetVcpuPinInfo(virDomainPtr domain, int ncpumaps, virCheckPositiveArgGoto(ncpumaps, error); virCheckPositiveArgGoto(maplen, error); - if (INT_MULTIPLY_OVERFLOW(ncpumaps, maplen)) { + if (VIR_INT_MULTIPLY_OVERFLOW(ncpumaps, maplen)) { virReportError(VIR_ERR_OVERFLOW, _("input too large: %d * %d"), ncpumaps, maplen); goto error; @@ -7503,7 +7501,7 @@ virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, else virCheckZeroArgGoto(maplen, error); - if (cpumaps && INT_MULTIPLY_OVERFLOW(maxinfo, maplen)) { + if (cpumaps && VIR_INT_MULTIPLY_OVERFLOW(maxinfo, maplen)) { virReportError(VIR_ERR_OVERFLOW, _("input too large: %d * %d"), maxinfo, maplen); goto error; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 9c294ddc39..6c00690f68 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -31,7 +31,6 @@ #include "remote_daemon_stream.h" #include "viruuid.h" #include "vircommand.h" -#include "intprops.h" #include "virnetserverservice.h" #include "virnetserver.h" #include "virfile.h" @@ -2755,7 +2754,7 @@ remoteDispatchDomainGetVcpuPinInfo(virNetServerPtr server G_GNUC_UNUSED, goto cleanup; } - if (INT_MULTIPLY_OVERFLOW(args->ncpumaps, args->maplen) || + if (VIR_INT_MULTIPLY_OVERFLOW(args->ncpumaps, args->maplen) || args->ncpumaps * args->maplen > REMOTE_CPUMAPS_MAX) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); goto cleanup; @@ -2898,7 +2897,7 @@ remoteDispatchDomainGetVcpus(virNetServerPtr server G_GNUC_UNUSED, goto cleanup; } - if (INT_MULTIPLY_OVERFLOW(args->maxinfo, args->maplen) || + if (VIR_INT_MULTIPLY_OVERFLOW(args->maxinfo, args->maplen) || args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); goto cleanup; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c11f73ab4d..66472a6cc1 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -43,7 +43,6 @@ #include "viralloc.h" #include "virfile.h" #include "vircommand.h" -#include "intprops.h" #include "virtypedparam.h" #include "viruri.h" #include "virauth.h" @@ -2236,7 +2235,7 @@ remoteDomainGetVcpuPinInfo(virDomainPtr domain, goto done; } - if (INT_MULTIPLY_OVERFLOW(ncpumaps, maplen) || + if (VIR_INT_MULTIPLY_OVERFLOW(ncpumaps, maplen) || ncpumaps * maplen > REMOTE_CPUMAPS_MAX) { virReportError(VIR_ERR_RPC, _("vCPU map buffer length exceeds maximum: %d > %d"), @@ -2405,7 +2404,7 @@ remoteDomainGetVcpus(virDomainPtr domain, maxinfo, REMOTE_VCPUINFO_MAX); goto done; } - if (INT_MULTIPLY_OVERFLOW(maxinfo, maplen) || + if (VIR_INT_MULTIPLY_OVERFLOW(maxinfo, maplen) || maxinfo * maplen > REMOTE_CPUMAPS_MAX) { virReportError(VIR_ERR_RPC, _("vCPU map buffer length exceeds maximum: %d > %d"), -- 2.24.1

On Thu, Jan 16, 2020 at 03:24:37PM +0000, Daniel P. Berrangé wrote:
The GLib g_size_checked_mul() function is not quite the same signature, and gives compiler warnings due to not correctly casting from gsize to guint64/32. Implementing a replacement for INT_MULTIPLY_OVERFLOW is easy enough to do ourselves.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 15 --------------- src/internal.h | 2 ++ src/libvirt-domain.c | 6 ++---- src/remote/remote_daemon_dispatch.c | 5 ++--- src/remote/remote_driver.c | 5 ++--- 5 files changed, 8 insertions(+), 25 deletions(-)
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>

Some UNIX platforms don't declare 'environ' in their header files. We can unconditionally declare it ourselves to avoid this problem. There is no need to do this in the aa-helper code since that is Linux only code. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- tests/commandhelper.c | 3 +++ tests/commandtest.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/commandhelper.c b/tests/commandhelper.c index 77cbcd4680..a7a3c44e33 100644 --- a/tests/commandhelper.c +++ b/tests/commandhelper.c @@ -31,6 +31,9 @@ #ifndef WIN32 +/* Some UNIX lack it in headers & it doesn't hurt to redeclare */ +extern char **environ; + # define VIR_FROM_THIS VIR_FROM_NONE static int envsort(const void *a, const void *b) diff --git a/tests/commandtest.c b/tests/commandtest.c index 5df1aa4221..cc8676811e 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -58,6 +58,9 @@ main(void) #else +/* Some UNIX lack it in headers & it doesn't hurt to redeclare */ +extern char **environ; + static int checkoutput(const char *testname, char *prefix) { -- 2.24.1

Some syntax check rules validate usage of headers provided by gnulib. We want to validate these only against the gnulib modules we've chosen to use, not all modules, since we're trying to eliminate them. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 3 --- 1 file changed, 3 deletions(-) diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 6e9328ee63..1fd11093d8 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -132,9 +132,6 @@ local-check := \ syntax-check: $(local-check) -# We use .gnulib, not gnulib. -gnulib_dir = $(srcdir)/.gnulib - # We haven't converted all scripts to using gnulib's init.sh yet. _test_script_regex = \<\(init\|test-lib\)\.sh\> -- 2.24.1

All UNIX platforms we care about have openpty() in the libutil library. Use of pty.h must also be made conditional, excluding Win32. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 3 +++ configure.ac | 4 ++++ src/util/Makefile.inc.am | 1 + src/util/virfile.c | 14 +++++++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 1fd11093d8..687a4ef368 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -2342,3 +2342,6 @@ exclude_file_name_regexp--sc_prohibit_strcmp = \ exclude_file_name_regexp--sc_prohibit_backslash_alignment = \ ^build-aux/syntax-check\.mk$$ + +exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ + ^src/util/virfile\.c$$ diff --git a/configure.ac b/configure.ac index 8837928358..b28ed4a6dc 100644 --- a/configure.ac +++ b/configure.ac @@ -383,10 +383,13 @@ dnl Availability of various common headers (non-fatal if missing). AC_CHECK_HEADERS([\ ifaddrs.h \ libtasn1.h \ + util.h \ + libutil.h \ linux/magic.h \ mntent.h \ net/ethernet.h \ netinet/tcp.h \ + pty.h \ pwd.h \ stdarg.h \ syslog.h \ @@ -430,6 +433,7 @@ dnl header could be found. AM_CONDITIONAL([HAVE_LIBTASN1], [test "x$ac_cv_header_libtasn1_h" = "xyes"]) AC_CHECK_LIB([intl],[gettext],[]) +AC_CHECK_LIB([util],[openpty],[]) dnl diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index dfa8347853..23de4a6375 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -282,6 +282,7 @@ libvirt_util_la_CFLAGS = \ $(NULL) libvirt_util_la_LIBADD = \ -lm \ + $(OPENPTY_LIBS) \ $(CAPNG_LIBS) \ $(YAJL_LIBS) \ $(LIBNL_LIBS) \ diff --git a/src/util/virfile.c b/src/util/virfile.c index 6eaabf5371..8bd03f8176 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -27,7 +27,19 @@ #include <passfd.h> #include <fcntl.h> -#include <pty.h> +#include <termios.h> +#ifdef HAVE_PTY_H +/* Linux openpty */ +# include <pty.h> +#endif /* !HAVE_PTY_H */ +#ifdef HAVE_UTIL_H +/* macOS openpty */ +# include <util.h> +#endif /* !HAVE_LIBUTIL_H */ +#ifdef HAVE_LIBUTIL_H +/* FreeBSD openpty */ +# include <libutil.h> +#endif /* !HAVE_LIBUTIL_H */ #include <sys/stat.h> #include <sys/types.h> #include <sys/socket.h> -- 2.24.1

Windows sockets take a SOCKET HANDLE object instead of a file descriptor. Wrap them in the same way that gnulib does so that they use C runtime file descriptors. While we could in theory use GSocket, it is hard to get the exact same semantics libvirt has for its current socket usage. Wrapping the Winsock2 APIs is thus the easiest approach in the short term. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/util/Makefile.inc.am | 2 + src/util/virsocket.c | 369 +++++++++++++++++++++++++++++++++++++++ src/util/virsocket.h | 92 ++++++++++ src/util/virutil.c | 29 ++- 4 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 src/util/virsocket.c create mode 100644 src/util/virsocket.h diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index 23de4a6375..528c9f6cfe 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -188,6 +188,8 @@ UTIL_SOURCES = \ util/virseclabel.h \ util/virsecret.c \ util/virsecret.h \ + util/virsocket.c \ + util/virsocket.h \ util/virsocketaddr.c \ util/virsocketaddr.h \ util/virstorageencryption.c \ diff --git a/src/util/virsocket.c b/src/util/virsocket.c new file mode 100644 index 0000000000..2d770b931b --- /dev/null +++ b/src/util/virsocket.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "virsocket.h" + +#ifdef WIN32 + +# include <fcntl.h> + +# define FD2SK(fd) _get_osfhandle(fd) +# define SK2FD(sk) (_open_osfhandle((intptr_t) (sk), O_RDWR | O_BINARY)) + +# define GET_HANDLE(fd) \ + +# define RETURN_ERROR(call) \ + if ((call) < 0) { \ + set_errno(); \ + return -1; \ + } + +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2 +# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket + +static void +set_errno(void) +{ + int err = WSAGetLastError(); + + /* Map some WSAE* errors to the runtime library's error codes. */ + switch (err) { + case WSA_INVALID_HANDLE: + errno = EBADF; + break; + case WSA_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + break; + case WSA_INVALID_PARAMETER: + errno = EINVAL; + break; + case WSAENAMETOOLONG: + errno = ENAMETOOLONG; + break; + case WSAENOTEMPTY: + errno = ENOTEMPTY; + break; + case WSAEWOULDBLOCK: + errno = EWOULDBLOCK; + break; + case WSAEINPROGRESS: + errno = EINPROGRESS; + break; + case WSAEALREADY: + errno = EALREADY; + break; + case WSAENOTSOCK: + errno = ENOTSOCK; + break; + case WSAEDESTADDRREQ: + errno = EDESTADDRREQ; + break; + case WSAEMSGSIZE: + errno = EMSGSIZE; + break; + case WSAEPROTOTYPE: + errno = EPROTOTYPE; + break; + case WSAENOPROTOOPT: + errno = ENOPROTOOPT; + break; + case WSAEPROTONOSUPPORT: + errno = EPROTONOSUPPORT; + break; + case WSAEOPNOTSUPP: + errno = EOPNOTSUPP; + break; + case WSAEAFNOSUPPORT: + errno = EAFNOSUPPORT; + break; + case WSAEADDRINUSE: + errno = EADDRINUSE; + break; + case WSAEADDRNOTAVAIL: + errno = EADDRNOTAVAIL; + break; + case WSAENETDOWN: + errno = ENETDOWN; + break; + case WSAENETUNREACH: + errno = ENETUNREACH; + break; + case WSAENETRESET: + errno = ENETRESET; + break; + case WSAECONNABORTED: + errno = ECONNABORTED; + break; + case WSAECONNRESET: + errno = ECONNRESET; + break; + case WSAENOBUFS: + errno = ENOBUFS; + break; + case WSAEISCONN: + errno = EISCONN; + break; + case WSAENOTCONN: + errno = ENOTCONN; + break; + case WSAETIMEDOUT: + errno = ETIMEDOUT; + break; + case WSAECONNREFUSED: + errno = ECONNREFUSED; + break; + case WSAELOOP: + errno = ELOOP; + break; + case WSAEHOSTUNREACH: + errno = EHOSTUNREACH; + break; + default: + errno = (err > 10000 && err < 10025) ? err - 10000 : err; + break; + } +} + + +int +vir_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) +{ + SOCKET sk = FD2SK(fd); + SOCKET csk; + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + csk = accept(sk, addr, addrlen); + + if (csk == INVALID_SOCKET) { + set_errno(); + return -1; + } + + return SK2FD(csk); +} + + +int +vir_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (bind(sk, addr, addrlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_closesocket(int fd) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (closesocket(sk) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (connect(sk, addr, addrlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (getpeername(sk, addr, addrlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (getsockname(sk, addr, addrlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_listen(int fd, int backlog) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (listen(sk, backlog) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_ioctlsocket(int fd, int cmd, void *arg) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (ioctlsocket(sk, cmd, arg) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_getsockopt(int fd, int level, int optname, + void *optval, socklen_t *optlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (getsockopt(sk, level, optname, optval, optlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_setsockopt(int fd, int level, int optname, + const void *optval, socklen_t optlen) +{ + SOCKET sk = FD2SK(fd); + + if (sk == INVALID_SOCKET) { + errno = EBADF; + return -1; + } + + if (setsockopt(sk, level, optname, optval, optlen) < 0) { + set_errno(); + return -1; + } + + return 0; +} + + +int +vir_socket(int domain, int type, int protocol) +{ + SOCKET sk; + + /* We have to use WSASocket() instead of socket(), to create + * non-overlapped IO sockets. Overlapped IO sockets cannot + * be used with read/write. + */ + sk = WSASocket(domain, type, protocol, NULL, 0, 0); + if (sk == INVALID_SOCKET) { + set_errno(); + return -1; + } + + return SK2FD(sk); +} + +#endif /* WIN32 */ diff --git a/src/util/virsocket.h b/src/util/virsocket.h new file mode 100644 index 0000000000..e9ef5380a3 --- /dev/null +++ b/src/util/virsocket.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "internal.h" + +#ifdef WIN32 + +# define WIN32_LEAN_AND_MEAN +# include <errno.h> +# include <winsock2.h> +# include <ws2tcpip.h> +# include <io.h> + +int vir_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_closesocket(int fd); +int vir_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_dup(int oldfd); +int vir_dup2(int oldfd, int newfd); +int vir_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_listen(int fd, int backlog); +int vir_ioctlsocket(int fd, int cmd, void *arg); +int vir_getsockopt(int fd, int level, int optname, + void *optval, socklen_t *optlen); +int vir_setsockopt(int fd, int level, int optname, + const void *optval, socklen_t optlen); +int vir_socket(int domain, int type, int protocol); + + +/* Get rid of GNULIB's replacements */ +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2 +# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket + +/* Provide our own replacements */ +# define accept vir_accept +# define bind vir_bind +# define closesocket vir_closesocket +# define connect vir_connect +# define dup _dup +# define dup2 _dup2 +# define ioctlsocket vir_ioctlsocket +# define getpeername vir_getpeername +# define getsockname vir_getsockname +# define getsockopt vir_getsockopt +# define listen vir_listen +# define setsockopt vir_setsockopt +# define socket vir_socket + +#else + +# include <sys/socket.h> +# include <unistd.h> +# include <sys/ioctl.h> +# include <arpa/inet.h> +# include <netinet/in.h> +# include <netinet/udp.h> +# include <netinet/tcp.h> +# include <sys/un.h> + +# define closesocket close +# define ioctlsocket ioctl + +#endif diff --git a/src/util/virutil.c b/src/util/virutil.c index a0fd7618ee..9ea9e2946d 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -71,10 +71,10 @@ #include "verify.h" #include "virfile.h" #include "vircommand.h" -#include "nonblocking.h" #include "virprocess.h" #include "virstring.h" #include "virutil.h" +#include "virsocket.h" verify(sizeof(gid_t) <= sizeof(unsigned int) && sizeof(uid_t) <= sizeof(unsigned int)); @@ -99,6 +99,21 @@ int virSetInherit(int fd, bool inherit) return 0; } + +int virSetBlocking(int fd, bool block) +{ + int fflags; + if ((fflags = fcntl(fd, F_GETFL)) < 0) + return -1; + if (block) + fflags &= ~O_NONBLOCK; + else + fflags |= O_NONBLOCK; + if ((fcntl(fd, F_SETFL, fflags)) < 0) + return -1; + return 0; +} + #else /* WIN32 */ int virSetInherit(int fd G_GNUC_UNUSED, bool inherit G_GNUC_UNUSED) @@ -110,13 +125,19 @@ int virSetInherit(int fd G_GNUC_UNUSED, bool inherit G_GNUC_UNUSED) return 0; } -#endif /* WIN32 */ - int virSetBlocking(int fd, bool blocking) { - return set_nonblocking_flag(fd, !blocking); + unsigned long arg = blocking ? 0 : 1; + + if (ioctlsocket(fd, FIONBIO, &arg) < 0) + return -1; + + return 0; } +#endif /* WIN32 */ + + int virSetNonBlock(int fd) { return virSetBlocking(fd, false); -- 2.24.1

On Thu, Jan 16, 2020 at 03:24:41PM +0000, Daniel P. Berrangé wrote:
Windows sockets take a SOCKET HANDLE object instead of a file descriptor. Wrap them in the same way that gnulib does so that they use C runtime file descriptors.
While we could in theory use GSocket, it is hard to get the exact same semantics libvirt has for its current socket usage. Wrapping the Winsock2 APIs is thus the easiest approach in the short term.
Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/util/Makefile.inc.am | 2 + src/util/virsocket.c | 369 +++++++++++++++++++++++++++++++++++++++ src/util/virsocket.h | 92 ++++++++++ src/util/virutil.c | 29 ++- 4 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 src/util/virsocket.c create mode 100644 src/util/virsocket.h
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index 23de4a6375..528c9f6cfe 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -188,6 +188,8 @@ UTIL_SOURCES = \ util/virseclabel.h \ util/virsecret.c \ util/virsecret.h \ + util/virsocket.c \ + util/virsocket.h \ util/virsocketaddr.c \ util/virsocketaddr.h \ util/virstorageencryption.c \ diff --git a/src/util/virsocket.c b/src/util/virsocket.c new file mode 100644 index 0000000000..2d770b931b --- /dev/null +++ b/src/util/virsocket.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "virsocket.h" + +#ifdef WIN32 + +# include <fcntl.h> + +# define FD2SK(fd) _get_osfhandle(fd) +# define SK2FD(sk) (_open_osfhandle((intptr_t) (sk), O_RDWR | O_BINARY)) + +# define GET_HANDLE(fd) \ + +# define RETURN_ERROR(call) \ + if ((call) < 0) { \ + set_errno(); \ + return -1; \ + } + +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2
We are not calling these two here so probably no need to undef here.
+# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket
[...]
diff --git a/src/util/virsocket.h b/src/util/virsocket.h new file mode 100644 index 0000000000..e9ef5380a3 --- /dev/null +++ b/src/util/virsocket.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "internal.h" + +#ifdef WIN32 + +# define WIN32_LEAN_AND_MEAN +# include <errno.h> +# include <winsock2.h> +# include <ws2tcpip.h> +# include <io.h> + +int vir_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_closesocket(int fd); +int vir_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_dup(int oldfd); +int vir_dup2(int oldfd, int newfd);
These two are not implemented anywhere as you are using the _dup and _dup2 from io.h.
+int vir_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_listen(int fd, int backlog); +int vir_ioctlsocket(int fd, int cmd, void *arg); +int vir_getsockopt(int fd, int level, int optname, + void *optval, socklen_t *optlen); +int vir_setsockopt(int fd, int level, int optname, + const void *optval, socklen_t optlen); +int vir_socket(int domain, int type, int protocol);
One nit that I missed in v1, the function declaration doesn't follow syntax style where each argument should be on separate line, but I don't care that much for these wrappers.
+ + +/* Get rid of GNULIB's replacements */ +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2 +# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket + +/* Provide our own replacements */ +# define accept vir_accept +# define bind vir_bind +# define closesocket vir_closesocket +# define connect vir_connect +# define dup _dup +# define dup2 _dup2 +# define ioctlsocket vir_ioctlsocket +# define getpeername vir_getpeername +# define getsockname vir_getsockname +# define getsockopt vir_getsockopt +# define listen vir_listen +# define setsockopt vir_setsockopt +# define socket vir_socket + +#else + +# include <sys/socket.h> +# include <unistd.h> +# include <sys/ioctl.h> +# include <arpa/inet.h> +# include <netinet/in.h> +# include <netinet/udp.h> +# include <netinet/tcp.h> +# include <sys/un.h> + +# define closesocket close +# define ioctlsocket ioctl + +#endif diff --git a/src/util/virutil.c b/src/util/virutil.c index a0fd7618ee..9ea9e2946d 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c
Changes to this should be in a separate patch but otherwise it looks good. Pavel

On Fri, Jan 17, 2020 at 10:27:05AM +0100, Pavel Hrdina wrote:
On Thu, Jan 16, 2020 at 03:24:41PM +0000, Daniel P. Berrangé wrote:
Windows sockets take a SOCKET HANDLE object instead of a file descriptor. Wrap them in the same way that gnulib does so that they use C runtime file descriptors.
While we could in theory use GSocket, it is hard to get the exact same semantics libvirt has for its current socket usage. Wrapping the Winsock2 APIs is thus the easiest approach in the short term.
Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/util/Makefile.inc.am | 2 + src/util/virsocket.c | 369 +++++++++++++++++++++++++++++++++++++++ src/util/virsocket.h | 92 ++++++++++ src/util/virutil.c | 29 ++- 4 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 src/util/virsocket.c create mode 100644 src/util/virsocket.h
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index 23de4a6375..528c9f6cfe 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -188,6 +188,8 @@ UTIL_SOURCES = \ util/virseclabel.h \ util/virsecret.c \ util/virsecret.h \ + util/virsocket.c \ + util/virsocket.h \ util/virsocketaddr.c \ util/virsocketaddr.h \ util/virstorageencryption.c \ diff --git a/src/util/virsocket.c b/src/util/virsocket.c new file mode 100644 index 0000000000..2d770b931b --- /dev/null +++ b/src/util/virsocket.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "virsocket.h" + +#ifdef WIN32 + +# include <fcntl.h> + +# define FD2SK(fd) _get_osfhandle(fd) +# define SK2FD(sk) (_open_osfhandle((intptr_t) (sk), O_RDWR | O_BINARY)) + +# define GET_HANDLE(fd) \ + +# define RETURN_ERROR(call) \ + if ((call) < 0) { \ + set_errno(); \ + return -1; \ + } + +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2
We are not calling these two here so probably no need to undef here.
+# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket
[...]
diff --git a/src/util/virsocket.h b/src/util/virsocket.h new file mode 100644 index 0000000000..e9ef5380a3 --- /dev/null +++ b/src/util/virsocket.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "internal.h" + +#ifdef WIN32 + +# define WIN32_LEAN_AND_MEAN +# include <errno.h> +# include <winsock2.h> +# include <ws2tcpip.h> +# include <io.h> + +int vir_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_closesocket(int fd); +int vir_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_dup(int oldfd); +int vir_dup2(int oldfd, int newfd);
These two are not implemented anywhere as you are using the _dup and _dup2 from io.h.
Opps, left over from earlier version when I did indeed replace dup/dup2.
+int vir_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_listen(int fd, int backlog); +int vir_ioctlsocket(int fd, int cmd, void *arg); +int vir_getsockopt(int fd, int level, int optname, + void *optval, socklen_t *optlen); +int vir_setsockopt(int fd, int level, int optname, + const void *optval, socklen_t optlen); +int vir_socket(int domain, int type, int protocol);
One nit that I missed in v1, the function declaration doesn't follow syntax style where each argument should be on separate line, but I don't care that much for these wrappers.
We've generally ignored that in the .h files in practice.
+ + +/* Get rid of GNULIB's replacements */ +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2 +# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket + +/* Provide our own replacements */ +# define accept vir_accept +# define bind vir_bind +# define closesocket vir_closesocket +# define connect vir_connect +# define dup _dup +# define dup2 _dup2 +# define ioctlsocket vir_ioctlsocket +# define getpeername vir_getpeername +# define getsockname vir_getsockname +# define getsockopt vir_getsockopt +# define listen vir_listen +# define setsockopt vir_setsockopt +# define socket vir_socket + +#else + +# include <sys/socket.h> +# include <unistd.h> +# include <sys/ioctl.h> +# include <arpa/inet.h> +# include <netinet/in.h> +# include <netinet/udp.h> +# include <netinet/tcp.h> +# include <sys/un.h> + +# define closesocket close +# define ioctlsocket ioctl + +#endif diff --git a/src/util/virutil.c b/src/util/virutil.c index a0fd7618ee..9ea9e2946d 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c
Changes to this should be in a separate patch but otherwise it looks good.
I did have it separately before, but it breaks bisectability, because the GNULIB socket wrappers & non-blocking impl are mutually dependant. 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 Fri, Jan 17, 2020 at 09:38:42AM +0000, Daniel P. Berrangé wrote:
On Fri, Jan 17, 2020 at 10:27:05AM +0100, Pavel Hrdina wrote:
On Thu, Jan 16, 2020 at 03:24:41PM +0000, Daniel P. Berrangé wrote:
Windows sockets take a SOCKET HANDLE object instead of a file descriptor. Wrap them in the same way that gnulib does so that they use C runtime file descriptors.
While we could in theory use GSocket, it is hard to get the exact same semantics libvirt has for its current socket usage. Wrapping the Winsock2 APIs is thus the easiest approach in the short term.
Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/util/Makefile.inc.am | 2 + src/util/virsocket.c | 369 +++++++++++++++++++++++++++++++++++++++ src/util/virsocket.h | 92 ++++++++++ src/util/virutil.c | 29 ++- 4 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 src/util/virsocket.c create mode 100644 src/util/virsocket.h
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index 23de4a6375..528c9f6cfe 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -188,6 +188,8 @@ UTIL_SOURCES = \ util/virseclabel.h \ util/virsecret.c \ util/virsecret.h \ + util/virsocket.c \ + util/virsocket.h \ util/virsocketaddr.c \ util/virsocketaddr.h \ util/virstorageencryption.c \ diff --git a/src/util/virsocket.c b/src/util/virsocket.c new file mode 100644 index 0000000000..2d770b931b --- /dev/null +++ b/src/util/virsocket.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "virsocket.h" + +#ifdef WIN32 + +# include <fcntl.h> + +# define FD2SK(fd) _get_osfhandle(fd) +# define SK2FD(sk) (_open_osfhandle((intptr_t) (sk), O_RDWR | O_BINARY)) + +# define GET_HANDLE(fd) \ + +# define RETURN_ERROR(call) \ + if ((call) < 0) { \ + set_errno(); \ + return -1; \ + } + +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2
We are not calling these two here so probably no need to undef here.
+# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket
[...]
diff --git a/src/util/virsocket.h b/src/util/virsocket.h new file mode 100644 index 0000000000..e9ef5380a3 --- /dev/null +++ b/src/util/virsocket.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "internal.h" + +#ifdef WIN32 + +# define WIN32_LEAN_AND_MEAN +# include <errno.h> +# include <winsock2.h> +# include <ws2tcpip.h> +# include <io.h> + +int vir_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_closesocket(int fd); +int vir_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); +int vir_dup(int oldfd); +int vir_dup2(int oldfd, int newfd);
These two are not implemented anywhere as you are using the _dup and _dup2 from io.h.
Opps, left over from earlier version when I did indeed replace dup/dup2.
+int vir_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); +int vir_listen(int fd, int backlog); +int vir_ioctlsocket(int fd, int cmd, void *arg); +int vir_getsockopt(int fd, int level, int optname, + void *optval, socklen_t *optlen); +int vir_setsockopt(int fd, int level, int optname, + const void *optval, socklen_t optlen); +int vir_socket(int domain, int type, int protocol);
One nit that I missed in v1, the function declaration doesn't follow syntax style where each argument should be on separate line, but I don't care that much for these wrappers.
We've generally ignored that in the .h files in practice.
+ + +/* Get rid of GNULIB's replacements */ +# undef accept +# undef bind +# undef closesocket +# undef connect +# undef dup +# undef dup2 +# undef getpeername +# undef getsockname +# undef getsockopt +# undef ioctlsocket +# undef listen +# undef setsockopt +# undef socket + +/* Provide our own replacements */ +# define accept vir_accept +# define bind vir_bind +# define closesocket vir_closesocket +# define connect vir_connect +# define dup _dup +# define dup2 _dup2 +# define ioctlsocket vir_ioctlsocket +# define getpeername vir_getpeername +# define getsockname vir_getsockname +# define getsockopt vir_getsockopt +# define listen vir_listen +# define setsockopt vir_setsockopt +# define socket vir_socket + +#else + +# include <sys/socket.h> +# include <unistd.h> +# include <sys/ioctl.h> +# include <arpa/inet.h> +# include <netinet/in.h> +# include <netinet/udp.h> +# include <netinet/tcp.h> +# include <sys/un.h> + +# define closesocket close +# define ioctlsocket ioctl + +#endif diff --git a/src/util/virutil.c b/src/util/virutil.c index a0fd7618ee..9ea9e2946d 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c
Changes to this should be in a separate patch but otherwise it looks good.
I did have it separately before, but it breaks bisectability, because the GNULIB socket wrappers & non-blocking impl are mutually dependant.
I see, in that case with the dup/dup2 fixes: Reviewed-by: Pavel Hrdina <phrdina@redhat.com>

Convert to use socket wrappers. Aside from the header file include change, this requires changing close -> closesocket since our portability isn't trying to replace the close function. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/rpc/virnetsocket.c | 34 +++++++++++++++++++++++----------- src/util/virportallocator.c | 8 +++----- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 9ad7c2cc28..973827ebde 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -44,6 +44,7 @@ # include <selinux/selinux.h> #endif +#include "virsocket.h" #include "virnetsocket.h" #include "virutil.h" #include "viralloc.h" @@ -403,7 +404,8 @@ int virNetSocketNewListenTCP(const char *nodename, goto error; } bindErrno = errno; - VIR_FORCE_CLOSE(fd); + closesocket(fd); + fd = -1; runp = runp->ai_next; continue; } @@ -454,7 +456,8 @@ int virNetSocketNewListenTCP(const char *nodename, virObjectUnref(socks[i]); VIR_FREE(socks); freeaddrinfo(ai); - VIR_FORCE_CLOSE(fd); + if (fd != -1) + closesocket(fd); return -1; } @@ -521,7 +524,8 @@ int virNetSocketNewListenUNIX(const char *path, error: if (path[0] != '@') unlink(path); - VIR_FORCE_CLOSE(fd); + if (fd != -1) + closesocket(fd); return -1; } #else @@ -605,7 +609,8 @@ int virNetSocketNewConnectTCP(const char *nodename, break; savedErrno = errno; - VIR_FORCE_CLOSE(fd); + closesocket(fd); + fd = -1; runp = runp->ai_next; } @@ -637,7 +642,8 @@ int virNetSocketNewConnectTCP(const char *nodename, error: freeaddrinfo(ai); - VIR_FORCE_CLOSE(fd); + if (fd != -1) + closesocket(fd); return -1; } @@ -758,8 +764,8 @@ int virNetSocketNewConnectUNIX(const char *path, VIR_FREE(lockpath); VIR_FREE(rundir); - if (ret < 0) - VIR_FORCE_CLOSE(fd); + if (ret < 0 && fd != -1) + closesocket(fd); return ret; } @@ -1370,8 +1376,10 @@ void virNetSocketDispose(void *obj) virObjectUnref(sock->libsshSession); #endif - if (sock->ownsFd) - VIR_FORCE_CLOSE(sock->fd); + if (sock->ownsFd && sock->fd != -1) { + closesocket(sock->fd); + sock->fd = -1; + } VIR_FORCE_CLOSE(sock->errfd); virProcessAbort(sock->pid); @@ -2144,7 +2152,8 @@ int virNetSocketAccept(virNetSocketPtr sock, virNetSocketPtr *clientsock) ret = 0; cleanup: - VIR_FORCE_CLOSE(fd); + if (fd != -1) + closesocket(fd); virObjectUnlock(sock); return ret; } @@ -2264,7 +2273,10 @@ void virNetSocketClose(virNetSocketPtr sock) virObjectLock(sock); - VIR_FORCE_CLOSE(sock->fd); + if (sock->fd != -1) { + closesocket(sock->fd); + sock->fd = -1; + } #ifdef HAVE_SYS_UN_H /* If a server socket, then unlink UNIX path */ diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c index 494bf9107a..285b8ddc45 100644 --- a/src/util/virportallocator.c +++ b/src/util/virportallocator.c @@ -21,10 +21,7 @@ #include <config.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/in.h> - +#include "virsocket.h" #include "viralloc.h" #include "virbitmap.h" #include "virportallocator.h" @@ -192,7 +189,8 @@ virPortAllocatorBindToPort(bool *used, ret = 0; cleanup: - VIR_FORCE_CLOSE(fd); + if (fd != -1) + closesocket(fd); return ret; } -- 2.24.1

We don't need all the platforms gnulib deals with, so this is a cut down version of GNULIB's physmem.c code. This also allows us to integrate libvirt's error reporting functions closer to the error cause. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 2 +- src/conf/capabilities.c | 1 - src/util/virhostcpu.c | 1 - src/util/virhostmem.c | 182 +++++++++++++++++++++++++++++++------- 4 files changed, 153 insertions(+), 33 deletions(-) diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 687a4ef368..359688ea54 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -2320,7 +2320,7 @@ exclude_file_name_regexp--sc_prohibit_virXXXFree = \ ^(docs/|tests/|examples/|tools/|build-aux/syntax-check\.mk|src/test/test_driver.c|src/libvirt_public.syms|include/libvirt/libvirt-(domain|network|nodedev|storage|stream|secret|nwfilter|interface|domain-snapshot).h|src/libvirt-(domain|qemu|network|nodedev|storage|stream|secret|nwfilter|interface|domain-snapshot).c$$) exclude_file_name_regexp--sc_prohibit_sysconf_pagesize = \ - ^(build-aux/syntax-check\.mk|src/util/virutil\.c)$$ + ^(build-aux/syntax-check\.mk|src/util/vir(hostmem|util)\.c)$$ exclude_file_name_regexp--sc_prohibit_pthread_create = \ ^(build-aux/syntax-check\.mk|src/util/virthread\.c|tests/.*)$$ diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 9a39858280..ade04b7cd6 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -26,7 +26,6 @@ #include "capabilities.h" #include "cpu_conf.h" #include "domain_conf.h" -#include "physmem.h" #include "storage_conf.h" #include "viralloc.h" #include "virarch.h" diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index f3adc1b4ae..a26e339a0a 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -41,7 +41,6 @@ #include "viralloc.h" #define LIBVIRT_VIRHOSTCPUPRIV_H_ALLOW #include "virhostcpupriv.h" -#include "physmem.h" #include "virerror.h" #include "virarch.h" #include "virfile.h" diff --git a/src/util/virhostmem.c b/src/util/virhostmem.c index 34e6f7adcf..9c08b9bd78 100644 --- a/src/util/virhostmem.c +++ b/src/util/virhostmem.c @@ -33,9 +33,13 @@ # include <sys/resource.h> #endif +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif + #include "viralloc.h" #include "virhostmem.h" -#include "physmem.h" #include "virerror.h" #include "virarch.h" #include "virfile.h" @@ -577,13 +581,151 @@ virHostMemGetParameters(virTypedParameterPtr params G_GNUC_UNUSED, } +#ifdef WIN32 +/* MEMORYSTATUSEX is missing from older windows headers, so define + a local replacement. */ +typedef struct +{ + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} lMEMORYSTATUSEX; +typedef WINBOOL(WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); +#endif /* !WIN32 */ + +static unsigned long long +virHostMemGetTotal(void) +{ +#if defined HAVE_SYSCTLBYNAME + /* This works on freebsd & macOS. */ + unsigned long long physmem = 0; + size_t len = sizeof(physmem); + + if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory total")); + return 0; + } + + return physmem; +#elif defined _SC_PHYS_PAGES && defined _SC_PAGESIZE + /* this works on linux */ + long long pages; + long long pagesize; + if ((pages = sysconf(_SC_PHYS_PAGES)) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory total")); + return 0; + } + if ((pagesize = sysconf(_SC_PAGESIZE)) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory page size")); + return 0; + } + return (unsigned long long)pages * (unsigned long long)pagesize; +#elif defined WIN32 + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle("kernel32.dll"); + + if (!h) { + virReportSystemError(errno, "%s", + _("Unable to access kernel32.dll")); + return 0; + } + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress(h, "GlobalMemoryStatusEx"))) { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof(lms_ex); + if (!pfnex(&lms_ex)) { + virReportSystemError(EIO, "%s", + _("Unable to query memory total")); + return 0; + } + return lms_ex.ullTotalPhys; + } else { + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB. */ + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + return ms.dwTotalPhys; + } +#endif +} + + +static unsigned long long +virHostMemGetAvailable(void) +{ +#if defined HAVE_SYSCTLBYNAME + /* This works on freebsd and macOS */ + unsigned long long usermem = 0; + size_t len = sizeof(usermem); + + if (sysctlbyname("hw.usermem", &usermem, &len, NULL, 0) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory available")); + return 0; + } + + return usermem; +#elif defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE + /* this works on linux */ + long long pages; + long long pagesize; + if ((pages = sysconf(_SC_AVPHYS_PAGES)) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory available")); + return 0; + } + if ((pagesize = sysconf(_SC_PAGESIZE)) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query memory page size")); + return 0; + } + return (unsigned long long)pages * (unsigned long long)pagesize; +#elif defined WIN32 + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle("kernel32.dll"); + + if (!h) { + virReportSystemError(errno, "%s", + _("Unable to access kernel32.dll")); + return 0; + } + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress(h, "GlobalMemoryStatusEx"))) { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof(lms_ex); + if (!pfnex(&lms_ex)) { + virReportSystemError(EIO, "%s", + _("Unable to query memory available")); + return 0; + } + return lms_ex.ullAvailPhys; + } else { + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB */ + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + return ms.dwAvailPhys; + } +#endif +} + + static int virHostMemGetCellsFreeFake(unsigned long long *freeMems, int startCell, int maxCells G_GNUC_UNUSED) { - double avail = physmem_available(); - if (startCell != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("start cell %d out of range (0-%d)"), @@ -591,13 +733,8 @@ virHostMemGetCellsFreeFake(unsigned long long *freeMems, return -1; } - freeMems[0] = (unsigned long long)avail; - - if (!freeMems[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot determine free memory")); + if ((freeMems[0] = virHostMemGetAvailable()) == 0) return -1; - } return 1; } @@ -606,28 +743,13 @@ static int virHostMemGetInfoFake(unsigned long long *mem, unsigned long long *freeMem) { - if (mem) { - double total = physmem_total(); - if (!total) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot determine free memory")); - return -1; - } - - *mem = (unsigned long long) total; - } - - if (freeMem) { - double avail = physmem_available(); - - if (!avail) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot determine free memory")); - return -1; - } + if (mem && + (*mem = virHostMemGetTotal()) == 0) + return -1; - *freeMem = (unsigned long long) avail; - } + if (freeMem && + (*freeMem = virHostMemGetAvailable()) == 0) + return -1; return 0; } -- 2.24.1

On Thu, Jan 16, 2020 at 03:24:43PM +0000, Daniel P. Berrangé wrote:
We don't need all the platforms gnulib deals with, so this is a cut down version of GNULIB's physmem.c code. This also allows us to integrate libvirt's error reporting functions closer to the error cause.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 2 +- src/conf/capabilities.c | 1 - src/util/virhostcpu.c | 1 - src/util/virhostmem.c | 182 +++++++++++++++++++++++++++++++------- 4 files changed, 153 insertions(+), 33 deletions(-)
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>

Libvirt's original atomic ops impls were largely copied from GLib's code at the time. The only API difference was that libvirt's virAtomicIntInc() would return a value, but g_atomic_int_inc was void. We thus use g_atomic_int_add(v, 1) instead, though this means virAtomicIntInc() now returns the original value, instead of the new value. This rewrites libvirt's impl in terms of g_atomic_int* as a short term conversion. The key motivation was to quickly eliminate use of GNULIB's verify_expr() macro which is not a direct match for G_STATIC_ASSERT_EXPR. Long term all the callers should be updated to use g_atomic_int* directly. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/libxl/libxl_domain.c | 2 +- src/libxl/libxl_driver.c | 2 +- src/lxc/lxc_process.c | 4 +- src/nwfilter/nwfilter_dhcpsnoop.c | 6 +- src/qemu/qemu_process.c | 4 +- src/util/viratomic.h | 351 ++---------------------------- src/util/virprocess.c | 2 +- tests/viratomictest.c | 2 +- 8 files changed, 26 insertions(+), 347 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 915aaeb8b0..f9be4ad583 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -1473,7 +1473,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver, if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0) goto destroy_dom; - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); /* finally we can call the 'started' hook script if any */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index f021ec9c5d..ef02a066d9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -446,7 +446,7 @@ libxlReconnectDomain(virDomainObjPtr vm, virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); /* Enable domain death events */ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 0a9ccdf9ec..af8593d6a5 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -1468,7 +1468,7 @@ int virLXCProcessStart(virConnectPtr conn, if (virCommandHandshakeNotify(cmd) < 0) goto cleanup; - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { @@ -1670,7 +1670,7 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm, virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index 9a71d13d57..f3acaf00dd 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -888,7 +888,7 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, skip_instantiate: VIR_FREE(ipl); - virAtomicIntDecAndTest(&virNWFilterSnoopState.nLeases); + ignore_value(virAtomicIntDecAndTest(&virNWFilterSnoopState.nLeases)); lease_not_found: VIR_FREE(ipstr); @@ -1167,7 +1167,7 @@ static void virNWFilterDHCPDecodeWorker(void *jobdata, void *opaque) _("Instantiation of rules failed on " "interface '%s'"), req->binding->portdevname); } - virAtomicIntDecAndTest(job->qCtr); + ignore_value(virAtomicIntDecAndTest(job->qCtr)); VIR_FREE(job); } @@ -1568,7 +1568,7 @@ virNWFilterDHCPSnoopThread(void *req0) pcap_close(pcapConf[i].handle); } - virAtomicIntDecAndTest(&virNWFilterSnoopState.nThreads); + ignore_value(virAtomicIntDecAndTest(&virNWFilterSnoopState.nThreads)); return; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a7bbab9e56..420d1c9c93 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5571,7 +5571,7 @@ qemuProcessInit(virQEMUDriverPtr driver, qemuDomainSetFakeReboot(driver, vm, false); virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_STARTING_UP); - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); /* Run an early hook to set-up missing devices */ @@ -8139,7 +8139,7 @@ qemuProcessReconnect(void *opaque) goto error; } - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + if (virAtomicIntInc(&driver->nactive) == 0 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); cleanup: diff --git a/src/util/viratomic.h b/src/util/viratomic.h index 9dfb77b992..12b116a6cd 100644 --- a/src/util/viratomic.h +++ b/src/util/viratomic.h @@ -1,11 +1,7 @@ /* * viratomic.h: atomic integer operations * - * Copyright (C) 2012 Red Hat, Inc. - * - * Based on code taken from GLib 2.32, under the LGPLv2+ - * - * Copyright (C) 2011 Ryan Lortie + * Copyright (C) 2012-2020 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 @@ -21,18 +17,15 @@ * License along with this library. If not, see * <http://www.gnu.org/licenses/>. * + * APIs in this header should no longer be used. Direct + * use of the g_atomic APIs is preferred & existing code + * should be converted as needed. */ #pragma once #include "internal.h" -#ifdef VIR_ATOMIC_OPS_GCC -# define VIR_STATIC /* Nothing; we just never define the functions */ -#else -# define VIR_STATIC static -#endif - /** * virAtomicIntGet: * Gets the current value of atomic. @@ -40,8 +33,7 @@ * This call acts as a full compiler and hardware memory barrier * (before the get) */ -VIR_STATIC int virAtomicIntGet(volatile int *atomic) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntGet(v) g_atomic_int_get(v) /** * virAtomicIntSet: @@ -50,21 +42,18 @@ VIR_STATIC int virAtomicIntGet(volatile int *atomic) * This call acts as a full compiler and hardware memory barrier * (after the set) */ -VIR_STATIC void virAtomicIntSet(volatile int *atomic, - int newval) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntSet(i, newv) g_atomic_int_set(i, newv) /** * virAtomicIntInc: * Increments the value of atomic by 1. * * Think of this operation as an atomic version of - * { *atomic += 1; return *atomic; } + * { tmp = *atomic; *atomic += 1; return tmp; } * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC int virAtomicIntInc(volatile int *atomic) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntInc(i) g_atomic_int_add(i, 1) /** * virAtomicIntDecAndTest: @@ -75,8 +64,7 @@ VIR_STATIC int virAtomicIntInc(volatile int *atomic) * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC bool virAtomicIntDecAndTest(volatile int *atomic) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntDecAndTest(i) (!!g_atomic_int_dec_and_test(i)) /** * virAtomicIntCompareExchange: @@ -91,10 +79,8 @@ VIR_STATIC bool virAtomicIntDecAndTest(volatile int *atomic) * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC bool virAtomicIntCompareExchange(volatile int *atomic, - int oldval, - int newval) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntCompareExchange(i, oldi, newi) \ + (!!g_atomic_int_compare_and_exchange(i, oldi, newi)) /** * virAtomicIntAdd: @@ -105,9 +91,7 @@ VIR_STATIC bool virAtomicIntCompareExchange(volatile int *atomic, * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC int virAtomicIntAdd(volatile int *atomic, - int val) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntAdd(i, v) g_atomic_int_add(i, v) /** * virAtomicIntAnd: @@ -119,9 +103,7 @@ VIR_STATIC int virAtomicIntAdd(volatile int *atomic, * Think of this operation as an atomic version of * { tmp = *atomic; *atomic &= val; return tmp; } */ -VIR_STATIC unsigned int virAtomicIntAnd(volatile unsigned int *atomic, - unsigned int val) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntAnd(i, v) g_atomic_int_and(i, v) /** * virAtomicIntOr: @@ -133,9 +115,7 @@ VIR_STATIC unsigned int virAtomicIntAnd(volatile unsigned int *atomic, * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC unsigned int virAtomicIntOr(volatile unsigned int *atomic, - unsigned int val) - ATTRIBUTE_NONNULL(1); +#define virAtomicIntOr(i, v) g_atomic_int_or(i, v) /** * virAtomicIntXor: @@ -147,305 +127,4 @@ VIR_STATIC unsigned int virAtomicIntOr(volatile unsigned int *atomic, * * This call acts as a full compiler and hardware memory barrier. */ -VIR_STATIC unsigned int virAtomicIntXor(volatile unsigned int *atomic, - unsigned int val) - ATTRIBUTE_NONNULL(1); - -#undef VIR_STATIC - -#ifdef VIR_ATOMIC_OPS_GCC - -# define virAtomicIntGet(atomic) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ *(atomic) : 0); \ - __sync_synchronize(); \ - (int)*(atomic); \ - })) -# define virAtomicIntSet(atomic, newval) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ (newval) : 0); \ - *(atomic) = (newval); \ - __sync_synchronize(); \ - })) -# define virAtomicIntInc(atomic) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ *(atomic) : 0); \ - __sync_add_and_fetch((atomic), 1); \ - })) -# define virAtomicIntDecAndTest(atomic) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ *(atomic) : 0); \ - __sync_fetch_and_sub((atomic), 1) == 1; \ - })) -# define virAtomicIntCompareExchange(atomic, oldval, newval) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ (newval) ^ (oldval) : 0); \ - (bool)__sync_bool_compare_and_swap((atomic), \ - (oldval), (newval)); \ - })) -# define virAtomicIntAdd(atomic, val) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void)(0 ? *(atomic) ^ (val) : 0); \ - (int) __sync_fetch_and_add((atomic), (val)); \ - })) -# define virAtomicIntAnd(atomic, val) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void) (0 ? *(atomic) ^ (val) : 0); \ - (unsigned int) __sync_fetch_and_and((atomic), (val)); \ - })) -# define virAtomicIntOr(atomic, val) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void) (0 ? *(atomic) ^ (val) : 0); \ - (unsigned int) __sync_fetch_and_or((atomic), (val)); \ - })) -# define virAtomicIntXor(atomic, val) \ - (__extension__ ({ \ - (void)verify_expr(sizeof(*(atomic)) == sizeof(int), 0); \ - (void) (0 ? *(atomic) ^ (val) : 0); \ - (unsigned int) __sync_fetch_and_xor((atomic), (val)); \ - })) - - -#else - -# ifdef VIR_ATOMIC_OPS_WIN32 - -# include <winsock2.h> -# include <windows.h> -# include <intrin.h> -# if !defined(_M_AMD64) && !defined (_M_IA64) && !defined(_M_X64) -# define InterlockedAnd _InterlockedAnd -# define InterlockedOr _InterlockedOr -# define InterlockedXor _InterlockedXor -# endif - -/* - * http://msdn.microsoft.com/en-us/library/ms684122(v=vs.85).aspx - */ -static inline int -virAtomicIntGet(volatile int *atomic) -{ - MemoryBarrier(); - return *atomic; -} - -static inline void -virAtomicIntSet(volatile int *atomic, - int newval) -{ - *atomic = newval; - MemoryBarrier(); -} - -static inline int -virAtomicIntInc(volatile int *atomic) -{ - return InterlockedIncrement((volatile LONG *)atomic); -} - -static inline bool -virAtomicIntDecAndTest(volatile int *atomic) -{ - return InterlockedDecrement((volatile LONG *)atomic) == 0; -} - -static inline bool -virAtomicIntCompareExchange(volatile int *atomic, - int oldval, - int newval) -{ - return InterlockedCompareExchange((volatile LONG *)atomic, newval, oldval) == oldval; -} - -static inline int -virAtomicIntAdd(volatile int *atomic, - int val) -{ - return InterlockedExchangeAdd((volatile LONG *)atomic, val); -} - -static inline unsigned int -virAtomicIntAnd(volatile unsigned int *atomic, - unsigned int val) -{ - return InterlockedAnd((volatile LONG *)atomic, val); -} - -static inline unsigned int -virAtomicIntOr(volatile unsigned int *atomic, - unsigned int val) -{ - return InterlockedOr((volatile LONG *)atomic, val); -} - -static inline unsigned int -virAtomicIntXor(volatile unsigned int *atomic, - unsigned int val) -{ - return InterlockedXor((volatile LONG *)atomic, val); -} - - -# else -# ifdef VIR_ATOMIC_OPS_PTHREAD -# include <pthread.h> - -extern pthread_mutex_t virAtomicLock; - -static inline int -virAtomicIntGet(volatile int *atomic) -{ - int value; - - pthread_mutex_lock(&virAtomicLock); - value = *atomic; - pthread_mutex_unlock(&virAtomicLock); - - return value; -} - -static inline void -virAtomicIntSet(volatile int *atomic, - int value) -{ - pthread_mutex_lock(&virAtomicLock); - *atomic = value; - pthread_mutex_unlock(&virAtomicLock); -} - -static inline int -virAtomicIntInc(volatile int *atomic) -{ - int value; - - pthread_mutex_lock(&virAtomicLock); - value = ++(*atomic); - pthread_mutex_unlock(&virAtomicLock); - - return value; -} - -static inline bool -virAtomicIntDecAndTest(volatile int *atomic) -{ - bool is_zero; - - pthread_mutex_lock(&virAtomicLock); - is_zero = --(*atomic) == 0; - pthread_mutex_unlock(&virAtomicLock); - - return is_zero; -} - -static inline bool -virAtomicIntCompareExchange(volatile int *atomic, - int oldval, - int newval) -{ - bool success; - - pthread_mutex_lock(&virAtomicLock); - - if ((success = (*atomic == oldval))) - *atomic = newval; - - pthread_mutex_unlock(&virAtomicLock); - - return success; -} - -static inline int -virAtomicIntAdd(volatile int *atomic, - int val) -{ - int oldval; - - pthread_mutex_lock(&virAtomicLock); - oldval = *atomic; - *atomic = oldval + val; - pthread_mutex_unlock(&virAtomicLock); - - return oldval; -} - -static inline unsigned int -virAtomicIntAnd(volatile unsigned int *atomic, - unsigned int val) -{ - unsigned int oldval; - - pthread_mutex_lock(&virAtomicLock); - oldval = *atomic; - *atomic = oldval & val; - pthread_mutex_unlock(&virAtomicLock); - - return oldval; -} - -static inline unsigned int -virAtomicIntOr(volatile unsigned int *atomic, - unsigned int val) -{ - unsigned int oldval; - - pthread_mutex_lock(&virAtomicLock); - oldval = *atomic; - *atomic = oldval | val; - pthread_mutex_unlock(&virAtomicLock); - - return oldval; -} - -static inline unsigned int -virAtomicIntXor(volatile unsigned int *atomic, - unsigned int val) -{ - unsigned int oldval; - - pthread_mutex_lock(&virAtomicLock); - oldval = *atomic; - *atomic = oldval ^ val; - pthread_mutex_unlock(&virAtomicLock); - - return oldval; -} - - -# else -# error "No atomic integer impl for this platform" -# endif -# endif - -/* The int/unsigned int casts here ensure that you can - * pass either an int or unsigned int to all atomic op - * functions, in the same way that we can with GCC - * atomic op helpers. - */ -# define virAtomicIntGet(atomic) \ - virAtomicIntGet((int *)atomic) -# define virAtomicIntSet(atomic, val) \ - virAtomicIntSet((int *)atomic, val) -# define virAtomicIntInc(atomic) \ - virAtomicIntInc((int *)atomic) -# define virAtomicIntDecAndTest(atomic) \ - virAtomicIntDecAndTest((int *)atomic) -# define virAtomicIntCompareExchange(atomic, oldval, newval) \ - virAtomicIntCompareExchange((int *)atomic, oldval, newval) -# define virAtomicIntAdd(atomic, val) \ - virAtomicIntAdd((int *)atomic, val) -# define virAtomicIntAnd(atomic, val) \ - virAtomicIntAnd((unsigned int *)atomic, val) -# define virAtomicIntOr(atomic, val) \ - virAtomicIntOr((unsigned int *)atomic, val) -# define virAtomicIntXor(atomic, val) \ - virAtomicIntXor((unsigned int *)atomic, val) - -#endif +#define virAtomicIntXor(i, v) g_atomic_int_xor(i, v) diff --git a/src/util/virprocess.c b/src/util/virprocess.c index 32f19e6b63..d5589daf6a 100644 --- a/src/util/virprocess.c +++ b/src/util/virprocess.c @@ -1021,7 +1021,7 @@ int virProcessGetStartTime(pid_t pid, unsigned long long *timestamp) { static int warned; - if (virAtomicIntInc(&warned) == 1) { + if (virAtomicIntInc(&warned) == 0) { VIR_WARN("Process start time of pid %lld not available on this platform", (long long) pid); } diff --git a/tests/viratomictest.c b/tests/viratomictest.c index 8c885a5b96..e30df66cd7 100644 --- a/tests/viratomictest.c +++ b/tests/viratomictest.c @@ -50,7 +50,7 @@ testTypes(const void *data G_GNUC_UNUSED) testAssertEq(virAtomicIntAdd(&u, 1), 5); testAssertEq(u, 6); - testAssertEq(virAtomicIntInc(&u), 7); + testAssertEq(virAtomicIntInc(&u), 6); testAssertEq(u, 7); res = virAtomicIntDecAndTest(&u); -- 2.24.1

G_STATIC_ASSERT() is a drop-in functional equivalent of the GNULIB verify() macro. Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- build-aux/syntax-check.mk | 6 ------ examples/c/misc/event-test.c | 12 ++++++------ src/conf/snapshot_conf.h | 2 +- src/conf/virdomaincheckpointobjlist.c | 8 ++++---- src/esx/esx_network_driver.c | 2 +- src/esx/esx_storage_backend_iscsi.c | 2 +- src/esx/esx_storage_backend_vmfs.c | 2 +- src/internal.h | 1 - src/libxl/xen_xm.c | 3 +-- src/nwfilter/nwfilter_dhcpsnoop.c | 4 ++-- src/qemu/qemu_blockjob.h | 4 ++-- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_firmware.h | 2 +- src/qemu/qemu_migration_params.c | 2 +- src/remote/remote_daemon_dispatch.c | 10 +++++----- src/util/virarch.c | 3 +-- src/util/vircgroup.h | 2 +- src/util/vircrypto.c | 2 +- src/util/virenum.h | 8 ++++---- src/util/virinitctl.c | 4 ++-- src/util/virkeycode.c | 22 +++++++++++----------- src/util/virmacaddr.h | 2 +- src/util/virobject.h | 8 ++++---- src/util/virperf.c | 2 +- src/util/virstoragefile.c | 4 ++-- src/util/virtypedparam.h | 2 +- src/util/virutil.c | 3 +-- src/vz/vz_driver.c | 2 +- tests/virstringtest.c | 7 +++---- tools/virsh-domain.c | 2 +- tools/virsh-network.c | 2 +- tools/virsh-nodedev.c | 2 +- tools/virsh-pool.c | 2 +- tools/virsh-secret.c | 2 +- tools/virt-host-validate-common.c | 4 ++-- 36 files changed, 69 insertions(+), 80 deletions(-) diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 359688ea54..b0a977201e 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -1621,12 +1621,6 @@ sc_prohibit_dirent_without_use: re='\<($(_dirent_syms_re))\>' \ $(_sc_header_without_use) -# Prohibit the inclusion of verify.h without an actual use. -sc_prohibit_verify_without_use: - @h='verify.h' \ - re='\<(verify(true|expr)?|assume|static_assert) *\(' \ - $(_sc_header_without_use) - # Don't include xfreopen.h unless you use one of its functions. sc_prohibit_xfreopen_without_use: @h='xfreopen.h' re='\<xfreopen *\(' $(_sc_header_without_use) diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c index ae282a5027..7e48cecc92 100644 --- a/examples/c/misc/event-test.c +++ b/examples/c/misc/event-test.c @@ -16,9 +16,9 @@ #if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \ && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \ && !defined __cplusplus) -# define verify(cond) _Static_assert(cond, "verify (" #cond ")") +# define G_STATIC_ASSERT(cond) _Static_assert(cond, "verify (" #cond ")") #else -# define verify(cond) +# define G_STATIC_ASSERT(cond) #endif #ifndef G_GNUC_UNUSED @@ -1138,10 +1138,10 @@ struct secretEventData secretEvents[] = { }; /* make sure that the events are kept in sync */ -verify(G_N_ELEMENTS(domainEvents) == VIR_DOMAIN_EVENT_ID_LAST); -verify(G_N_ELEMENTS(storagePoolEvents) == VIR_STORAGE_POOL_EVENT_ID_LAST); -verify(G_N_ELEMENTS(nodeDeviceEvents) == VIR_NODE_DEVICE_EVENT_ID_LAST); -verify(G_N_ELEMENTS(secretEvents) == VIR_SECRET_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(domainEvents) == VIR_DOMAIN_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(storagePoolEvents) == VIR_STORAGE_POOL_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(nodeDeviceEvents) == VIR_NODE_DEVICE_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(secretEvents) == VIR_SECRET_EVENT_ID_LAST); int main(int argc, char **argv) diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index c02d0fa263..b5b1ef2718 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -56,7 +56,7 @@ typedef enum { VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT, VIR_DOMAIN_SNAPSHOT_LAST } virDomainSnapshotState; -verify((int)VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT == VIR_DOMAIN_LAST); +G_STATIC_ASSERT((int)VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT == VIR_DOMAIN_LAST); /* Stores disk-snapshot information */ typedef struct _virDomainSnapshotDiskDef virDomainSnapshotDiskDef; diff --git a/src/conf/virdomaincheckpointobjlist.c b/src/conf/virdomaincheckpointobjlist.c index 41181477f4..a4942ea706 100644 --- a/src/conf/virdomaincheckpointobjlist.c +++ b/src/conf/virdomaincheckpointobjlist.c @@ -91,13 +91,13 @@ virDomainCheckpointObjListGetNames(virDomainCheckpointObjListPtr checkpoints, unsigned int flags) { /* We intentionally chose our public flags to match the common flags */ - verify(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS == + G_STATIC_ASSERT(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS == (int) VIR_DOMAIN_MOMENT_LIST_ROOTS); - verify(VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL == + G_STATIC_ASSERT(VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL == (int) VIR_DOMAIN_MOMENT_LIST_TOPOLOGICAL); - verify(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES == + G_STATIC_ASSERT(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES == (int) VIR_DOMAIN_MOMENT_LIST_LEAVES); - verify(VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES == + G_STATIC_ASSERT(VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES == (int) VIR_DOMAIN_MOMENT_LIST_NO_LEAVES); return virDomainMomentObjListGetNames(checkpoints->base, from, names, diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c index 4f359c61e2..0d52818e18 100644 --- a/src/esx/esx_network_driver.c +++ b/src/esx/esx_network_driver.c @@ -41,7 +41,7 @@ * The UUID of a network is the MD5 sum of its key. Therefore, verify that * UUID and MD5 sum match in size, because we rely on that. */ -verify(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); +G_STATIC_ASSERT(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); static int diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c index 72ab0d3cb0..395a347cf3 100644 --- a/src/esx/esx_storage_backend_iscsi.c +++ b/src/esx/esx_storage_backend_iscsi.c @@ -43,7 +43,7 @@ * The UUID of a storage pool is the MD5 sum of its mount path. Therefore, * verify that UUID and MD5 sum match in size, because we rely on that. */ -verify(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); +G_STATIC_ASSERT(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c index 61b30c3c1d..4f613bf93b 100644 --- a/src/esx/esx_storage_backend_vmfs.c +++ b/src/esx/esx_storage_backend_vmfs.c @@ -49,7 +49,7 @@ VIR_LOG_INIT("esx.esx_storage_backend_vmfs"); * The UUID of a storage pool is the MD5 sum of its mount path. Therefore, * verify that UUID and MD5 sum match in size, because we rely on that. */ -verify(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); +G_STATIC_ASSERT(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); diff --git a/src/internal.h b/src/internal.h index e356db6c78..4b0286e237 100644 --- a/src/internal.h +++ b/src/internal.h @@ -22,7 +22,6 @@ #include <errno.h> #include <limits.h> -#include <verify.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> diff --git a/src/libxl/xen_xm.c b/src/libxl/xen_xm.c index 5d5d521c18..54eb6fc97d 100644 --- a/src/libxl/xen_xm.c +++ b/src/libxl/xen_xm.c @@ -26,7 +26,6 @@ #include "virerror.h" #include "virconf.h" #include "viralloc.h" -#include "verify.h" #include "xenxs_private.h" #include "xen_xm.h" #include "domain_conf.h" @@ -581,7 +580,7 @@ xenFormatXMInputDevs(virConfPtr conf, virDomainDefPtr def) /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is either 32, or 64 on a platform where long is big enough. */ -verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT); +G_STATIC_ASSERT(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT); /* * Convert a virDomainDef object into an XM config record. diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index f3acaf00dd..629f974177 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -186,7 +186,7 @@ struct _virNWFilterSnoopEthHdr { uint16_t eh_type; uint8_t eh_data[]; } ATTRIBUTE_PACKED; -verify(sizeof(struct _virNWFilterSnoopEthHdr) == 14); +G_STATIC_ASSERT(sizeof(struct _virNWFilterSnoopEthHdr) == 14); typedef struct _virNWFilterSnoopDHCPHdr virNWFilterSnoopDHCPHdr; typedef virNWFilterSnoopDHCPHdr *virNWFilterSnoopDHCPHdrPtr; @@ -208,7 +208,7 @@ struct _virNWFilterSnoopDHCPHdr { char d_file[128]; uint8_t d_opts[]; } ATTRIBUTE_PACKED; -verify(sizeof(struct _virNWFilterSnoopDHCPHdr) == 236); +G_STATIC_ASSERT(sizeof(struct _virNWFilterSnoopDHCPHdr) == 236); /* DHCP options */ diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index 7d584a2980..2f29e8209c 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -44,7 +44,7 @@ typedef enum { QEMU_BLOCKJOB_STATE_PIVOTING, QEMU_BLOCKJOB_STATE_LAST } qemuBlockjobState; -verify((int)QEMU_BLOCKJOB_STATE_NEW == VIR_DOMAIN_BLOCK_JOB_LAST); +G_STATIC_ASSERT((int)QEMU_BLOCKJOB_STATE_NEW == VIR_DOMAIN_BLOCK_JOB_LAST); VIR_ENUM_DECL(qemuBlockjobState); @@ -67,7 +67,7 @@ typedef enum { QEMU_BLOCKJOB_TYPE_BROKEN, QEMU_BLOCKJOB_TYPE_LAST } qemuBlockJobType; -verify((int)QEMU_BLOCKJOB_TYPE_INTERNAL == VIR_DOMAIN_BLOCK_JOB_TYPE_LAST); +G_STATIC_ASSERT((int)QEMU_BLOCKJOB_TYPE_INTERNAL == VIR_DOMAIN_BLOCK_JOB_TYPE_LAST); VIR_ENUM_DECL(qemuBlockjob); diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 84c62a4e28..697f07ece3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2490,7 +2490,7 @@ static const char *preferredMachines[] = "sim", /* VIR_ARCH_XTENSA */ "sim", /* VIR_ARCH_XTENSAEB */ }; -verify(G_N_ELEMENTS(preferredMachines) == VIR_ARCH_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(preferredMachines) == VIR_ARCH_LAST); void diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 62d7b581f4..4862d75923 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2765,7 +2765,7 @@ qemuDomainGetControlInfo(virDomainPtr dom, #define QEMU_SAVE_PARTIAL "LibvirtQemudPart" #define QEMU_SAVE_VERSION 2 -verify(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL)); +G_STATIC_ASSERT(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL)); typedef enum { QEMU_SAVE_FORMAT_RAW = 0, diff --git a/src/qemu/qemu_firmware.h b/src/qemu/qemu_firmware.h index 37cbfae39d..2fdd71ba52 100644 --- a/src/qemu/qemu_firmware.h +++ b/src/qemu/qemu_firmware.h @@ -57,4 +57,4 @@ qemuFirmwareGetSupported(const char *machine, virFirmwarePtr **fws, size_t *nfws); -verify(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST <= 64); +G_STATIC_ASSERT(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST <= 64); diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index 9430ce1d00..1b28e5e031 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -218,7 +218,7 @@ static const qemuMigrationParamType qemuMigrationParamTypes[] = { [QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = QEMU_MIGRATION_PARAM_TYPE_ULL, [QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = QEMU_MIGRATION_PARAM_TYPE_INT, }; -verify(G_N_ELEMENTS(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST); virBitmapPtr diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 6c00690f68..df4733b3ba 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -1331,7 +1331,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), }; -verify(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); static int remoteRelayNetworkEventLifecycle(virConnectPtr conn, @@ -1368,7 +1368,7 @@ static virConnectNetworkEventGenericCallback networkEventCallbacks[] = { VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle), }; -verify(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); static int remoteRelayStoragePoolEventLifecycle(virConnectPtr conn, @@ -1435,7 +1435,7 @@ static virConnectStoragePoolEventGenericCallback storageEventCallbacks[] = { VIR_STORAGE_POOL_EVENT_CALLBACK(remoteRelayStoragePoolEventRefresh), }; -verify(G_N_ELEMENTS(storageEventCallbacks) == VIR_STORAGE_POOL_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(storageEventCallbacks) == VIR_STORAGE_POOL_EVENT_ID_LAST); static int remoteRelayNodeDeviceEventLifecycle(virConnectPtr conn, @@ -1502,7 +1502,7 @@ static virConnectNodeDeviceEventGenericCallback nodeDeviceEventCallbacks[] = { VIR_NODE_DEVICE_EVENT_CALLBACK(remoteRelayNodeDeviceEventUpdate), }; -verify(G_N_ELEMENTS(nodeDeviceEventCallbacks) == VIR_NODE_DEVICE_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(nodeDeviceEventCallbacks) == VIR_NODE_DEVICE_EVENT_ID_LAST); static int remoteRelaySecretEventLifecycle(virConnectPtr conn, @@ -1569,7 +1569,7 @@ static virConnectSecretEventGenericCallback secretEventCallbacks[] = { VIR_SECRET_EVENT_CALLBACK(remoteRelaySecretEventValueChanged), }; -verify(G_N_ELEMENTS(secretEventCallbacks) == VIR_SECRET_EVENT_ID_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(secretEventCallbacks) == VIR_SECRET_EVENT_ID_LAST); static void remoteRelayDomainQemuMonitorEvent(virConnectPtr conn, diff --git a/src/util/virarch.c b/src/util/virarch.c index f41e3e86bb..b132e178c3 100644 --- a/src/util/virarch.c +++ b/src/util/virarch.c @@ -25,7 +25,6 @@ #include "virlog.h" #include "virarch.h" -#include "verify.h" VIR_LOG_INIT("util.arch"); @@ -81,7 +80,7 @@ static const struct virArchData { { "xtensaeb", 32, VIR_ARCH_BIG_ENDIAN }, }; -verify(G_N_ELEMENTS(virArchData) == VIR_ARCH_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(virArchData) == VIR_ARCH_LAST); /** diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index 3eefe78787..15263f534a 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -49,7 +49,7 @@ VIR_ENUM_DECL(virCgroupController); * bit array stored in int. Like this: * 1 << VIR_CGROUP_CONTROLLER_CPU * Make sure we will not overflow */ -verify(VIR_CGROUP_CONTROLLER_LAST < 8 * sizeof(int)); +G_STATIC_ASSERT(VIR_CGROUP_CONTROLLER_LAST < 8 * sizeof(int)); typedef enum { VIR_CGROUP_THREAD_VCPU = 0, diff --git a/src/util/vircrypto.c b/src/util/vircrypto.c index 87fabfbba1..90aed32c53 100644 --- a/src/util/vircrypto.c +++ b/src/util/vircrypto.c @@ -47,7 +47,7 @@ struct virHashInfo { }; -verify(G_N_ELEMENTS(hashinfo) == VIR_CRYPTO_HASH_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(hashinfo) == VIR_CRYPTO_HASH_LAST); ssize_t virCryptoHashBuf(virCryptoHash hash, diff --git a/src/util/virenum.h b/src/util/virenum.h index d68421b203..d74af35530 100644 --- a/src/util/virenum.h +++ b/src/util/virenum.h @@ -42,7 +42,7 @@ virEnumToString(const char * const *types, G_N_ELEMENTS(name ## TypeList), \ type); \ } \ - verify(G_N_ELEMENTS(name ## TypeList) == lastVal) + G_STATIC_ASSERT(G_N_ELEMENTS(name ## TypeList) == lastVal) #define VIR_ENUM_DECL(name) \ const char *name ## TypeToString(int type); \ @@ -72,6 +72,6 @@ virTristateSwitch virTristateSwitchFromBool(bool val); /* the two enums must be in sync to be able to use helpers interchangeably in * some special cases */ -verify((int)VIR_TRISTATE_BOOL_YES == (int)VIR_TRISTATE_SWITCH_ON); -verify((int)VIR_TRISTATE_BOOL_NO == (int)VIR_TRISTATE_SWITCH_OFF); -verify((int)VIR_TRISTATE_BOOL_ABSENT == (int)VIR_TRISTATE_SWITCH_ABSENT); +G_STATIC_ASSERT((int)VIR_TRISTATE_BOOL_YES == (int)VIR_TRISTATE_SWITCH_ON); +G_STATIC_ASSERT((int)VIR_TRISTATE_BOOL_NO == (int)VIR_TRISTATE_SWITCH_OFF); +G_STATIC_ASSERT((int)VIR_TRISTATE_BOOL_ABSENT == (int)VIR_TRISTATE_SWITCH_ABSENT); diff --git a/src/util/virinitctl.c b/src/util/virinitctl.c index 955e8f398e..d7e29f24c3 100644 --- a/src/util/virinitctl.c +++ b/src/util/virinitctl.c @@ -96,9 +96,9 @@ struct virInitctlRequest { }; # ifdef MAXHOSTNAMELEN - verify(sizeof(struct virInitctlRequest) == 320 + MAXHOSTNAMELEN); + G_STATIC_ASSERT(sizeof(struct virInitctlRequest) == 320 + MAXHOSTNAMELEN); # else - verify(sizeof(struct virInitctlRequest) == 384); + G_STATIC_ASSERT(sizeof(struct virInitctlRequest) == 384); # endif diff --git a/src/util/virkeycode.c b/src/util/virkeycode.c index 1a0a94e3ab..1475f69b84 100644 --- a/src/util/virkeycode.c +++ b/src/util/virkeycode.c @@ -56,17 +56,17 @@ static const unsigned short *virKeymapValues[VIR_KEYCODE_SET_LAST] = { #define VIR_KEYMAP_ENTRY_MAX G_N_ELEMENTS(virKeyCodeTable_linux) -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset1)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset2)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset3)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_osx)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_xtkbd)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_usb)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_win32)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_qnum)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_linux)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_osx)); -verify(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_win32)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset1)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset2)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_atset3)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_osx)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_xtkbd)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_usb)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_win32)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyCodeTable_qnum)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_linux)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_osx)); +G_STATIC_ASSERT(VIR_KEYMAP_ENTRY_MAX == G_N_ELEMENTS(virKeyNameTable_win32)); VIR_ENUM_IMPL(virKeycodeSet, VIR_KEYCODE_SET_LAST, diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h index 0296cfa965..e43ac3f32a 100644 --- a/src/util/virmacaddr.h +++ b/src/util/virmacaddr.h @@ -38,7 +38,7 @@ struct _virMacAddr { * must not have any extra members added - it must remain exactly * 6 bytes in length. */ -verify(sizeof(struct _virMacAddr) == 6); +G_STATIC_ASSERT(sizeof(struct _virMacAddr) == 6); int virMacAddrCompare(const char *mac1, const char *mac2); diff --git a/src/util/virobject.h b/src/util/virobject.h index 5c4bcf4dde..62a8a3d132 100644 --- a/src/util/virobject.h +++ b/src/util/virobject.h @@ -80,10 +80,10 @@ virClassPtr virClassForObjectRWLockable(void); * function or as a macro defined to NULL. */ #define VIR_CLASS_NEW(name, prnt) \ - verify_expr(offsetof(name, parent) == 0, \ - (name##Class = virClassNew(prnt, #name, sizeof(name), \ - sizeof(((name *)NULL)->parent), \ - name##Dispose))) + (G_STATIC_ASSERT_EXPR(offsetof(name, parent) == 0), \ + (name##Class = virClassNew(prnt, #name, sizeof(name),\ + sizeof(((name *)NULL)->parent), \ + name##Dispose))) virClassPtr virClassNew(virClassPtr parent, diff --git a/src/util/virperf.c b/src/util/virperf.c index fe2c3f8864..29c388a1f2 100644 --- a/src/util/virperf.c +++ b/src/util/virperf.c @@ -168,7 +168,7 @@ static struct virPerfEventAttr attrs[] = { .attrConfig = PERF_COUNT_SW_EMULATION_FAULTS }, }; -verify(G_N_ELEMENTS(attrs) == VIR_PERF_EVENT_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(attrs) == VIR_PERF_EVENT_LAST); typedef struct virPerfEventAttr *virPerfEventAttrPtr; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 1397f532fd..90e9b6796e 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -386,7 +386,7 @@ static struct FileTypeInfo const fileTypeInfo[] = { 4+4+4, 8, 512, NULL, vmdk4GetBackingStore, NULL }, }; -verify(G_N_ELEMENTS(fileTypeInfo) == VIR_STORAGE_FILE_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(fileTypeInfo) == VIR_STORAGE_FILE_LAST); /* qcow2 compatible features in the order they appear on-disk */ @@ -400,7 +400,7 @@ enum qcow2CompatibleFeature { static const int qcow2CompatibleFeatureArray[] = { VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS, }; -verify(G_N_ELEMENTS(qcow2CompatibleFeatureArray) == +G_STATIC_ASSERT(G_N_ELEMENTS(qcow2CompatibleFeatureArray) == QCOW2_COMPATIBLE_FEATURE_LAST); static int diff --git a/src/util/virtypedparam.h b/src/util/virtypedparam.h index ea48ee5009..3ac2e68144 100644 --- a/src/util/virtypedparam.h +++ b/src/util/virtypedparam.h @@ -33,7 +33,7 @@ */ #define VIR_TYPED_PARAM_MULTIPLE (1U << 31) -verify(!(VIR_TYPED_PARAM_LAST & VIR_TYPED_PARAM_MULTIPLE)); +G_STATIC_ASSERT(!(VIR_TYPED_PARAM_LAST & VIR_TYPED_PARAM_MULTIPLE)); typedef struct _virTypedParameterRemoteValue virTypedParameterRemoteValue; typedef struct virTypedParameterRemoteValue *virTypedParameterRemoteValuePtr; diff --git a/src/util/virutil.c b/src/util/virutil.c index 9ea9e2946d..c14c02a8c4 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -68,7 +68,6 @@ #include "virlog.h" #include "virbuffer.h" #include "viralloc.h" -#include "verify.h" #include "virfile.h" #include "vircommand.h" #include "virprocess.h" @@ -76,7 +75,7 @@ #include "virutil.h" #include "virsocket.h" -verify(sizeof(gid_t) <= sizeof(unsigned int) && +G_STATIC_ASSERT(sizeof(gid_t) <= sizeof(unsigned int) && sizeof(uid_t) <= sizeof(unsigned int)); #define VIR_FROM_THIS VIR_FROM_NONE diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index bcdbb50404..bd427fb07e 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -122,7 +122,7 @@ vzBuildCapabilities(void) if (virCapabilitiesInitCaches(caps) < 0) goto error; - verify(G_N_ELEMENTS(archs) == G_N_ELEMENTS(emulators)); + G_STATIC_ASSERT(G_N_ELEMENTS(archs) == G_N_ELEMENTS(emulators)); for (i = 0; i < G_N_ELEMENTS(ostypes); i++) for (j = 0; j < G_N_ELEMENTS(archs); j++) diff --git a/tests/virstringtest.c b/tests/virstringtest.c index 1f195ab4b9..88f50185e5 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -20,7 +20,6 @@ #include "testutils.h" -#include "verify.h" #include "virerror.h" #include "viralloc.h" #include "virfile.h" @@ -420,9 +419,9 @@ struct stringToLongData { * not guaranteed by POSIX. Good luck to you if you are crazy enough * to try and port libvirt to a platform with 16-bit int. Gnulib * already assumes that signed integers are two's complement. */ -verify(sizeof(int) == 4); -verify(sizeof(long) == sizeof(int) || sizeof(long) == sizeof(long long)); -verify(sizeof(long long) == 8); +G_STATIC_ASSERT(sizeof(int) == 4); +G_STATIC_ASSERT(sizeof(long) == sizeof(int) || sizeof(long) == sizeof(long long)); +G_STATIC_ASSERT(sizeof(long long) == 8); static int testStringToLong(const void *opaque) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index ac8ac33582..c48575279c 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13513,7 +13513,7 @@ virshDomainEventCallback virshDomainEventCallbacks[] = { { "block-threshold", VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), }, }; -verify(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks)); +G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks)); static const vshCmdInfo info_event[] = { {.name = "help", diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 700cb0d3e1..a02c85fcb1 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -1242,7 +1242,7 @@ virshNetworkEventCallback virshNetworkEventCallbacks[] = { { "lifecycle", VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint), }, }; -verify(VIR_NETWORK_EVENT_ID_LAST == G_N_ELEMENTS(virshNetworkEventCallbacks)); +G_STATIC_ASSERT(VIR_NETWORK_EVENT_ID_LAST == G_N_ELEMENTS(virshNetworkEventCallbacks)); static const vshCmdInfo info_network_event[] = { {.name = "help", diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index cb2fc26d1a..68790ea802 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -845,7 +845,7 @@ virshNodeDeviceEventCallback virshNodeDeviceEventCallbacks[] = { VIR_NODE_DEVICE_EVENT_CALLBACK(vshEventLifecyclePrint), }, { "update", vshEventGenericPrint, } }; -verify(VIR_NODE_DEVICE_EVENT_ID_LAST == G_N_ELEMENTS(virshNodeDeviceEventCallbacks)); +G_STATIC_ASSERT(VIR_NODE_DEVICE_EVENT_ID_LAST == G_N_ELEMENTS(virshNodeDeviceEventCallbacks)); static const vshCmdInfo info_node_device_event[] = { diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index feae0787cb..9c32449fbb 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -1972,7 +1972,7 @@ virshPoolEventCallback virshPoolEventCallbacks[] = { VIR_STORAGE_POOL_EVENT_CALLBACK(vshEventLifecyclePrint), }, { "refresh", vshEventGenericPrint, } }; -verify(VIR_STORAGE_POOL_EVENT_ID_LAST == G_N_ELEMENTS(virshPoolEventCallbacks)); +G_STATIC_ASSERT(VIR_STORAGE_POOL_EVENT_ID_LAST == G_N_ELEMENTS(virshPoolEventCallbacks)); static const vshCmdInfo info_pool_event[] = { diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c index 66369a25dc..01c62b9ce8 100644 --- a/tools/virsh-secret.c +++ b/tools/virsh-secret.c @@ -649,7 +649,7 @@ virshSecretEventCallback virshSecretEventCallbacks[] = { VIR_SECRET_EVENT_CALLBACK(vshEventLifecyclePrint), }, { "value-changed", vshEventGenericPrint, }, }; -verify(VIR_SECRET_EVENT_ID_LAST == G_N_ELEMENTS(virshSecretEventCallbacks)); +G_STATIC_ASSERT(VIR_SECRET_EVENT_ID_LAST == G_N_ELEMENTS(virshSecretEventCallbacks)); static const vshCmdInfo info_secret_event[] = { {.name = "help", diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index bce0f14917..6a715ede76 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -96,7 +96,7 @@ static const char * failMessages[] = { N_("NOTE"), }; -verify(G_N_ELEMENTS(failMessages) == VIR_HOST_VALIDATE_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(failMessages) == VIR_HOST_VALIDATE_LAST); static const char *failEscapeCodes[] = { "\033[31m", @@ -104,7 +104,7 @@ static const char *failEscapeCodes[] = { "\033[34m", }; -verify(G_N_ELEMENTS(failEscapeCodes) == VIR_HOST_VALIDATE_LAST); +G_STATIC_ASSERT(G_N_ELEMENTS(failEscapeCodes) == VIR_HOST_VALIDATE_LAST); void virHostMsgFail(virHostValidateLevel level, const char *format, -- 2.24.1

The GNULIB termios module ensures termios.h exists (but is none the less empty) when building for Windows. We already exclude usage of the functions that would exist in a real termios.h, so having an empty termios.h is not especially useful. It is simpler to just put all use of termios.h related functions behind a "#ifndef WIN32" conditional. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- configure.ac | 1 - src/util/virfdstream.c | 10 ++++++---- src/util/virfile.c | 4 +++- src/util/virutil.c | 1 - tools/virsh.h | 1 - tools/vsh.c | 15 --------------- tools/vsh.h | 4 +++- 7 files changed, 12 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index b28ed4a6dc..7d69b8bcb4 100644 --- a/configure.ac +++ b/configure.ac @@ -353,7 +353,6 @@ AC_CHECK_SIZEOF([long]) dnl Availability of various common functions (non-fatal if missing), dnl and various less common threadsafe functions AC_CHECK_FUNCS_ONCE([\ - cfmakeraw \ fallocate \ geteuid \ getgid \ diff --git a/src/util/virfdstream.c b/src/util/virfdstream.c index 719185d992..a903107afb 100644 --- a/src/util/virfdstream.c +++ b/src/util/virfdstream.c @@ -31,7 +31,9 @@ # include <sys/un.h> #endif #include <netinet/in.h> -#include <termios.h> +#ifndef WIN32 +# include <termios.h> +#endif #include "virfdstream.h" #include "virerror.h" @@ -1361,7 +1363,7 @@ int virFDStreamCreateFile(virStreamPtr st, false, false); } -#ifdef HAVE_CFMAKERAW +#ifndef WIN32 int virFDStreamOpenPTY(virStreamPtr st, const char *path, unsigned long long offset, @@ -1401,7 +1403,7 @@ int virFDStreamOpenPTY(virStreamPtr st, virFDStreamClose(st); return -1; } -#else /* !HAVE_CFMAKERAW */ +#else /* WIN32 */ int virFDStreamOpenPTY(virStreamPtr st, const char *path, unsigned long long offset, @@ -1413,7 +1415,7 @@ int virFDStreamOpenPTY(virStreamPtr st, oflags | O_CREAT, 0, false, false); } -#endif /* !HAVE_CFMAKERAW */ +#endif /* WIN32 */ int virFDStreamOpenBlockDevice(virStreamPtr st, const char *path, diff --git a/src/util/virfile.c b/src/util/virfile.c index 8bd03f8176..b3a63fa2ea 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -27,7 +27,9 @@ #include <passfd.h> #include <fcntl.h> -#include <termios.h> +#ifndef WIN32 +# include <termios.h> +#endif /* !WIN32 */ #ifdef HAVE_PTY_H /* Linux openpty */ # include <pty.h> diff --git a/src/util/virutil.c b/src/util/virutil.c index c14c02a8c4..7c2c5a78f6 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -35,7 +35,6 @@ #endif #include <sys/types.h> -#include <termios.h> #if WITH_DEVMAPPER # include <libdevmapper.h> diff --git a/tools/virsh.h b/tools/virsh.h index 903a2e53b6..fa9e54b1d1 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -23,7 +23,6 @@ #include <stdarg.h> #include <unistd.h> #include <sys/stat.h> -#include <termios.h> #include "internal.h" #include "virerror.h" diff --git a/tools/vsh.c b/tools/vsh.c index a36b6bfe23..5c8908f240 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1928,21 +1928,6 @@ vshTTYRestore(vshControl *ctl G_GNUC_UNUSED) } -#if !defined(WIN32) && !defined(HAVE_CFMAKERAW) -/* provide fallback in case cfmakeraw isn't available */ -static void -cfmakeraw(struct termios *attr) -{ - attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP - | INLCR | IGNCR | ICRNL | IXON); - attr->c_oflag &= ~OPOST; - attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - attr->c_cflag &= ~(CSIZE | PARENB); - attr->c_cflag |= CS8; -} -#endif /* !WIN32 && !HAVE_CFMAKERAW */ - - int vshTTYMakeRaw(vshControl *ctl G_GNUC_UNUSED, bool report_errors G_GNUC_UNUSED) diff --git a/tools/vsh.h b/tools/vsh.h index 960cae8df0..174116b369 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -23,7 +23,9 @@ #include <stdarg.h> #include <unistd.h> #include <sys/stat.h> -#include <termios.h> +#ifndef WIN32 +# include <termios.h> +#endif #include "internal.h" #include "virerror.h" -- 2.24.1

On Thu, Jan 16, 2020 at 03:24:46PM +0000, Daniel P. Berrangé wrote:
The GNULIB termios module ensures termios.h exists (but is none the less empty) when building for Windows. We already exclude usage of the functions that would exist in a real termios.h, so having an empty termios.h is not especially useful.
It is simpler to just put all use of termios.h related functions behind a "#ifndef WIN32" conditional.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- configure.ac | 1 - src/util/virfdstream.c | 10 ++++++---- src/util/virfile.c | 4 +++- src/util/virutil.c | 1 - tools/virsh.h | 1 - tools/vsh.c | 15 --------------- tools/vsh.h | 4 +++- 7 files changed, 12 insertions(+), 24 deletions(-)
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>

gmtime_r/localtime_r are mostly used in combination with strftime to format timestamps in libvirt. This can all be replaced with GDateTime resulting in simpler code that is also more portable. There is some boundary condition problem in parsing POSIX timezone offsets in GLib which tickles our test suite. The test suite is hacked to avoid the problem. The upsteam GLib bug report is https://gitlab.gnome.org/GNOME/glib/issues/1999 Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 11 ++++---- src/libxl/libxl_domain.c | 10 +++---- src/qemu/qemu_command.c | 17 ++++------- src/qemu/qemu_driver.c | 10 +++---- src/util/virtime.c | 35 ++++------------------- tests/qemuxml2argvmock.c | 12 ++++---- tests/virtimetest.c | 39 +++++++++++++------------ tools/virsh-checkpoint.c | 20 +++++-------- tools/virsh-domain-monitor.c | 14 ++++----- tools/virsh-domain.c | 13 ++++----- tools/virsh-network.c | 11 ++++---- tools/virsh-snapshot.c | 19 ++++--------- tools/virt-admin.c | 55 ++++++++---------------------------- tools/vsh.c | 16 ++++------- 14 files changed, 96 insertions(+), 186 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 2a8a04cacb..91ddad4d86 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -26789,11 +26789,12 @@ virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf, def->passwd); if (def->expires) { - char strbuf[100]; - struct tm tmbuf, *tm; - tm = gmtime_r(&def->validTo, &tmbuf); - strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm); - virBufferAsprintf(buf, " passwdValidTo='%s'", strbuf); + g_autoptr(GDateTime) then = NULL; + g_autofree char *thenstr = NULL; + + then = g_date_time_new_from_unix_utc(def->validTo); + thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S"); + virBufferAsprintf(buf, " passwdValidTo='%s'", thenstr); } if (def->connected) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index f9be4ad583..d63eca0bd6 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -943,16 +943,14 @@ libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver); - time_t curtime = time(NULL); - char timestr[100]; - struct tm time_info; + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + g_autofree char *nowstr = NULL; char *dumpfile = NULL; - localtime_r(&curtime, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info); + nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S"); dumpfile = g_strdup_printf("%s/%s-%s", cfg->autoDumpDir, vm->def->name, - timestr); + nowstr); /* Unlock virDomainObj while dumping core */ virObjectUnlock(vm); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 904d2beab5..62cd3be7c4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6070,8 +6070,9 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) break; case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: { - time_t now = time(NULL); - struct tm nowbits; + g_autoptr(GDateTime) now = g_date_time_new_now_utc(); + g_autoptr(GDateTime) then = NULL; + g_autofree char *thenstr = NULL; if (def->data.variable.basis == VIR_DOMAIN_CLOCK_BASIS_LOCALTIME) { long localOffset; @@ -6094,8 +6095,8 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) def->data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC; } - now += def->data.variable.adjustment; - gmtime_r(&now, &nowbits); + then = g_date_time_add_seconds(now, def->data.variable.adjustment); + thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S"); /* when an RTC_CHANGE event is received from qemu, we need to * have the adjustment used at domain start time available to @@ -6105,13 +6106,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) */ def->data.variable.adjustment0 = def->data.variable.adjustment; - virBufferAsprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d", - nowbits.tm_year + 1900, - nowbits.tm_mon + 1, - nowbits.tm_mday, - nowbits.tm_hour, - nowbits.tm_min, - nowbits.tm_sec); + virBufferAsprintf(&buf, "base=%s", thenstr); } break; default: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4862d75923..b73079001a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4090,9 +4090,8 @@ getAutoDumpPath(virQEMUDriverPtr driver, virDomainObjPtr vm) { g_autofree char *domname = virDomainDefGetShortName(vm->def); - char timestr[100]; - struct tm time_info; - time_t curtime = time(NULL); + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + g_autofree char *nowstr = NULL; g_autoptr(virQEMUDriverConfig) cfg = NULL; if (!domname) @@ -4100,10 +4099,9 @@ getAutoDumpPath(virQEMUDriverPtr driver, cfg = virQEMUDriverGetConfig(driver); - localtime_r(&curtime, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info); + nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S"); - return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, timestr); + return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, nowstr); } static void diff --git a/src/util/virtime.c b/src/util/virtime.c index 13f899cb91..bc8f06cd48 100644 --- a/src/util/virtime.c +++ b/src/util/virtime.c @@ -302,8 +302,8 @@ char *virTimeStringThen(unsigned long long when) /** * virTimeLocalOffsetFromUTC: * - * This function is threadsafe, but is *not* async signal safe (due to - * gmtime_r() and mktime()). + * This function is threadsafe, but is *not* async signal safe + * due to use of GLib APIs. * * @offset: pointer to time_t that will be set to the difference * between localtime and UTC in seconds (east of UTC is a @@ -314,34 +314,11 @@ char *virTimeStringThen(unsigned long long when) int virTimeLocalOffsetFromUTC(long *offset) { - struct tm gmtimeinfo; - time_t current, utc; + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + GTimeSpan diff = g_date_time_get_utc_offset(now); - /* time() gives seconds since Epoch in current timezone */ - if ((current = time(NULL)) == (time_t)-1) { - virReportSystemError(errno, "%s", - _("failed to get current system time")); - return -1; - } - - /* treat current as if it were in UTC */ - if (!gmtime_r(¤t, &gmtimeinfo)) { - virReportSystemError(errno, "%s", - _("gmtime_r failed")); - return -1; - } - - /* tell mktime to figure out itself whether or not DST is in effect */ - gmtimeinfo.tm_isdst = -1; - - /* mktime() also obeys current timezone rules */ - if ((utc = mktime(&gmtimeinfo)) == (time_t)-1) { - virReportSystemError(errno, "%s", - _("mktime failed")); - return -1; - } - - *offset = current - utc; + /* GTimeSpan measures microseconds, we want seconds */ + *offset = diff / 1000000; return 0; } diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c index 8143de1618..e5841bc8e3 100644 --- a/tests/qemuxml2argvmock.c +++ b/tests/qemuxml2argvmock.c @@ -47,12 +47,14 @@ long virGetSystemPageSize(void) return 4096; } -time_t time(time_t *t) +GDateTime *g_date_time_new_now_utc(void) { - const time_t ret = 1234567890; - if (t) - *t = ret; - return ret; + return g_date_time_new_from_unix_utc(1234567890); +} + +GDateTime *g_date_time_new_now_local(void) +{ + return g_date_time_new_from_unix_local(1234567890); } bool diff --git a/tests/virtimetest.c b/tests/virtimetest.c index f8a81ff090..f9ac55192d 100644 --- a/tests/virtimetest.c +++ b/tests/virtimetest.c @@ -101,20 +101,12 @@ testTimeLocalOffset(const void *args) static bool isNearYearEnd(void) { - time_t current = time(NULL); - struct tm timeinfo; + g_autoptr(GDateTime) now = g_date_time_new_now_local(); - if (current == (time_t)-1) { - VIR_DEBUG("time() failed"); - return false; - } - if (!localtime_r(¤t, &timeinfo)) { - VIR_DEBUG("localtime_r() failed"); - return false; - } - - return (timeinfo.tm_mon == 0 && timeinfo.tm_mday == 1) || - (timeinfo.tm_mon == 11 && timeinfo.tm_mday == 31); + return ((g_date_time_get_month(now) == 1 && + g_date_time_get_day_of_month(now) == 1) || + (g_date_time_get_month(now) == 12 && + g_date_time_get_day_of_month(now) == 31)); } @@ -186,14 +178,21 @@ mymain(void) /* test DST processing with timezones that always * have DST in effect; what's more, cover a zone with * with an unusual DST different than a usual one hour + * + * These tests originally used '0' as the first day, + * but changed to '1' due to GLib GTimeZone parsing bug: + * https://gitlab.gnome.org/GNOME/glib/issues/1999 + * + * Once we depend on a new enough GLib, we can put then + * back to 0 again. */ - TEST_LOCALOFFSET("VIR-00:30VID,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR-00:30VID,1/00:00:00,364/23:59:59", ((1 * 60) + 30) * 60); - TEST_LOCALOFFSET("VIR-02:30VID,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR-02:30VID,1/00:00:00,364/23:59:59", ((3 * 60) + 30) * 60); - TEST_LOCALOFFSET("VIR-02:30VID-04:30,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR-02:30VID-04:30,1/00:00:00,364/23:59:59", ((4 * 60) + 30) * 60); - TEST_LOCALOFFSET("VIR-12:00VID-13:00,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR-12:00VID-13:00,1/00:00:00,364/23:59:59", ((13 * 60) + 0) * 60); if (!isNearYearEnd()) { @@ -209,11 +208,11 @@ mymain(void) * tests, except on Dec 31 and Jan 1. */ - TEST_LOCALOFFSET("VIR02:45VID00:45,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR02:45VID00:45,1/00:00:00,364/23:59:59", -45 * 60); - TEST_LOCALOFFSET("VIR05:00VID04:00,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR05:00VID04:00,1/00:00:00,364/23:59:59", ((-4 * 60) + 0) * 60); - TEST_LOCALOFFSET("VIR11:00VID10:00,0/00:00:00,365/23:59:59", + TEST_LOCALOFFSET("VIR11:00VID10:00,1/00:00:00,364/23:59:59", ((-10 * 60) + 0) * 60); } diff --git a/tools/virsh-checkpoint.c b/tools/virsh-checkpoint.c index f9749b5f6d..e82a67f075 100644 --- a/tools/virsh-checkpoint.c +++ b/tools/virsh-checkpoint.c @@ -719,9 +719,8 @@ cmdCheckpointList(vshControl *ctl, char *doc = NULL; virDomainCheckpointPtr checkpoint = NULL; long long creation_longlong; - time_t creation_time_t; - char timestr[100]; - struct tm time_info; + g_autoptr(GDateTime) then = NULL; + g_autofree gchar *thenstr = NULL; bool tree = vshCommandOptBool(cmd, "tree"); bool name = vshCommandOptBool(cmd, "name"); bool from = vshCommandOptBool(cmd, "from"); @@ -835,21 +834,16 @@ cmdCheckpointList(vshControl *ctl, if (virXPathLongLong("string(/domaincheckpoint/creationTime)", ctxt, &creation_longlong) < 0) continue; - creation_time_t = creation_longlong; - if (creation_time_t != creation_longlong) { - vshError(ctl, "%s", _("time_t overflow")); - continue; - } - localtime_r(&creation_time_t, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", - &time_info); + + then = g_date_time_new_from_unix_local(creation_longlong); + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S %z"); if (parent) { - if (vshTableRowAppend(table, chk_name, timestr, + if (vshTableRowAppend(table, chk_name, thenstr, NULLSTR_EMPTY(parent_chk), NULL) < 0) goto cleanup; } else { - if (vshTableRowAppend(table, chk_name, timestr, NULL) < 0) + if (vshTableRowAppend(table, chk_name, thenstr, NULL) < 0) goto cleanup; } } diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index efcdc613c6..933e2aa75f 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -1534,17 +1534,13 @@ cmdDomTime(vshControl *ctl, const vshCmd *cmd) goto cleanup; if (pretty) { - char timestr[100]; - time_t cur_time = seconds; - struct tm time_info; + g_autoptr(GDateTime) then = NULL; + g_autofree char *thenstr = NULL; - if (!gmtime_r(&cur_time, &time_info)) { - vshError(ctl, _("Unable to format time")); - goto cleanup; - } - strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", &time_info); + then = g_date_time_new_from_unix_utc(seconds); + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S"); - vshPrint(ctl, _("Time: %s"), timestr); + vshPrint(ctl, _("Time: %s"), thenstr); } else { vshPrint(ctl, _("Time: %lld"), seconds); } diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index c48575279c..e64e08e5da 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5492,9 +5492,8 @@ static const vshCmdOptDef opts_screenshot[] = { static char * virshGenFileName(vshControl *ctl, virDomainPtr dom, const char *mime) { - char timestr[100]; - time_t cur_time; - struct tm time_info; + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + g_autofree char *nowstr = NULL; const char *ext = NULL; char *ret = NULL; @@ -5509,12 +5508,10 @@ virshGenFileName(vshControl *ctl, virDomainPtr dom, const char *mime) ext = ".png"; /* add mime type here */ - time(&cur_time); - localtime_r(&cur_time, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info); + nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S"); - ret = g_strdup_printf("%s-%s%s", virDomainGetName(dom), timestr, - NULLSTR_EMPTY(ext)); + ret = g_strdup_printf("%s-%s%s", virDomainGetName(dom), + nowstr, NULLSTR_EMPTY(ext)); return ret; } diff --git a/tools/virsh-network.c b/tools/virsh-network.c index a02c85fcb1..ed90736345 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -1433,11 +1433,10 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd) const char *typestr = NULL; g_autofree char *cidr_format = NULL; virNetworkDHCPLeasePtr lease = leases[i]; - time_t expirytime_tmp = lease->expirytime; - struct tm ts; - char expirytime[32]; - localtime_r(&expirytime_tmp, &ts); - strftime(expirytime, sizeof(expirytime), "%Y-%m-%d %H:%M:%S", &ts); + g_autoptr(GDateTime) then = g_date_time_new_from_unix_local(lease->expirytime); + g_autofree char *thenstr = NULL; + + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S"); if (lease->type == VIR_IP_ADDR_TYPE_IPV4) typestr = "ipv4"; @@ -1447,7 +1446,7 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd) cidr_format = g_strdup_printf("%s/%d", lease->ipaddr, lease->prefix); if (vshTableRowAppend(table, - expirytime, + thenstr, NULLSTR_MINUS(lease->mac), NULLSTR_MINUS(typestr), NULLSTR_MINUS(cidr_format), diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index a42397b42e..d5e68e4b18 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -1492,9 +1492,8 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) virDomainSnapshotPtr snapshot = NULL; char *state = NULL; long long creation_longlong; - time_t creation_time_t; - char timestr[100]; - struct tm time_info; + g_autoptr(GDateTime) then = NULL; + g_autofree gchar *thenstr = NULL; bool tree = vshCommandOptBool(cmd, "tree"); bool name = vshCommandOptBool(cmd, "name"); bool from = vshCommandOptBool(cmd, "from"); @@ -1624,22 +1623,16 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) if (virXPathLongLong("string(/domainsnapshot/creationTime)", ctxt, &creation_longlong) < 0) continue; - creation_time_t = creation_longlong; - if (creation_time_t != creation_longlong) { - vshError(ctl, "%s", _("time_t overflow")); - continue; - } - localtime_r(&creation_time_t, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", - &time_info); + then = g_date_time_new_from_unix_local(creation_longlong); + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S %z"); if (parent) { - if (vshTableRowAppend(table, snap_name, timestr, state, + if (vshTableRowAppend(table, snap_name, thenstr, state, NULLSTR_EMPTY(parent_snap), NULL) < 0) goto cleanup; } else { - if (vshTableRowAppend(table, snap_name, timestr, state, + if (vshTableRowAppend(table, snap_name, thenstr, state, NULL) < 0) goto cleanup; } diff --git a/tools/virt-admin.c b/tools/virt-admin.c index 30106d1971..c71ebb1012 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -69,40 +69,6 @@ vshAdmClientTransportToString(int transport) return str ? _(str) : _("unknown"); } -/* - * vshAdmGetTimeStr: - * - * Produces string representation (local time) of @then - * (seconds since epoch UTC) using format 'YYYY-MM-DD HH:MM:SS+ZZZZ'. - * - * Returns 0 if conversion finished successfully, -1 in case of an error. - * Caller is responsible for freeing the string returned. - */ -static int -vshAdmGetTimeStr(vshControl *ctl, time_t then, char **result) -{ - char *tmp = NULL; - struct tm timeinfo; - - if (!localtime_r(&then, &timeinfo)) - goto error; - - if (VIR_ALLOC_N(tmp, VIRT_ADMIN_TIME_BUFLEN) < 0) - goto error; - - if (strftime(tmp, VIRT_ADMIN_TIME_BUFLEN, "%Y-%m-%d %H:%M:%S%z", - &timeinfo) == 0) { - VIR_FREE(tmp); - goto error; - } - - *result = tmp; - return 0; - - error: - vshError(ctl, "%s", _("Timestamp string conversion failed")); - return -1; -} /* * vshAdmCatchDisconnect: @@ -646,19 +612,19 @@ cmdSrvClientsList(vshControl *ctl, const vshCmd *cmd) goto cleanup; for (i = 0; i < nclts; i++) { - g_autofree char *timestr = NULL; + g_autoptr(GDateTime) then = NULL; + g_autofree gchar *thenstr = NULL; g_autofree char *idStr = NULL; virAdmClientPtr client = clts[i]; id = virAdmClientGetID(client); + then = g_date_time_new_from_unix_local(virAdmClientGetTimestamp(client)); transport = virAdmClientGetTransport(client); - if (vshAdmGetTimeStr(ctl, virAdmClientGetTimestamp(client), - ×tr) < 0) - goto cleanup; + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S%z"); idStr = g_strdup_printf("%llu", id); if (vshTableRowAppend(table, idStr, vshAdmClientTransportToString(transport), - timestr, NULL) < 0) + thenstr, NULL) < 0) goto cleanup; } @@ -714,7 +680,8 @@ cmdClientInfo(vshControl *ctl, const vshCmd *cmd) size_t i; unsigned long long id; const char *srvname = NULL; - char *timestr = NULL; + g_autoptr(GDateTime) then = NULL; + g_autofree gchar *thenstr = NULL; virAdmServerPtr srv = NULL; virAdmClientPtr clnt = NULL; virTypedParameterPtr params = NULL; @@ -739,12 +706,13 @@ cmdClientInfo(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if (vshAdmGetTimeStr(ctl, virAdmClientGetTimestamp(clnt), ×tr) < 0) - goto cleanup; + + then = g_date_time_new_from_unix_local(virAdmClientGetTimestamp(clnt)); + thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S%z"); /* this info is provided by the client object itself */ vshPrint(ctl, "%-15s: %llu\n", "id", virAdmClientGetID(clnt)); - vshPrint(ctl, "%-15s: %s\n", "connection_time", timestr); + vshPrint(ctl, "%-15s: %s\n", "connection_time", thenstr); vshPrint(ctl, "%-15s: %s\n", "transport", vshAdmClientTransportToString(virAdmClientGetTransport(clnt))); @@ -760,7 +728,6 @@ cmdClientInfo(vshControl *ctl, const vshCmd *cmd) virTypedParamsFree(params, nparams); virAdmServerFree(srv); virAdmClientFree(clnt); - VIR_FREE(timestr); return ret; } diff --git a/tools/vsh.c b/tools/vsh.c index 5c8908f240..949c8dad7b 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -2182,8 +2182,8 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, char *str = NULL; size_t len; const char *lvl = ""; - time_t stTime; - struct tm stTm; + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + g_autofree gchar *nowstr = NULL; if (ctl->log_fd == -1) return; @@ -2193,15 +2193,9 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, * * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message */ - time(&stTime); - localtime_r(&stTime, &stTm); - virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ", - (1900 + stTm.tm_year), - (1 + stTm.tm_mon), - stTm.tm_mday, - stTm.tm_hour, - stTm.tm_min, - stTm.tm_sec, + nowstr = g_date_time_format(now, "%Y.%m.%d %H:%M:%S"); + virBufferAsprintf(&buf, "[%s %s %d] ", + nowstr, ctl->progname, (int) getpid()); switch (log_level) { -- 2.24.1

* send, recv: we use write & read for sockets so don't need these portability wrappers * ioctl, fcntl, fcntl-h: any usage of these is conditionally compiled and excludes Windows * ttyname_r: this exists in all supported platforms that we require now * environ: the tests explicitly declare this global variable * intprops: the code has been converted / simplified * openpty: custom checks in configure.ac cope with portability * accept, bind, connect, getpeername, getsockname, listen, setsockopt, socket: code needing Windows portability uses our wrapper functions * close: avoids abort when passed invalid FD on Windows. Our VIR_FORCE_CLOSE wrapper avoids calling close(-1) and it is reasonable to abort in other scenarios in the RPC client * physmem: the gnulib code has been partially imported * warnings, manywarnings: copy the files directly into our local m4 dir * verify: replaced by G_STATIC_ASSERT * pthread_sigmask: none of the fixed portability problems affect libvirt's usage on current supported platforms * termios: the header is now conditionally included only when needed * time_r: replaced with GDateTime APIs Reviewed-by: Pavel Hrdina <phrdina@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- bootstrap.conf | 50 ------ m4/virt-manywarnings.m4 | 339 ++++++++++++++++++++++++++++++++++++++++ m4/virt-warnings.m4 | 115 ++++++++++++++ 3 files changed, 454 insertions(+), 50 deletions(-) create mode 100644 m4/virt-manywarnings.m4 create mode 100644 m4/virt-warnings.m4 diff --git a/bootstrap.conf b/bootstrap.conf index ae9ecb4039..7e550a379c 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -24,44 +24,18 @@ # turning it into a FD, since closing an FD also closes # the original HANDLE. -# -> GSocket -gnulib_modules="$gnulib_modules accept" -# -> GSocket -gnulib_modules="$gnulib_modules bind" # -> conditional build to avoid Win32 gnulib_modules="$gnulib_modules chown" -# -> GSocket -gnulib_modules="$gnulib_modules close" -# -> GSocket -gnulib_modules="$gnulib_modules connect" # -> Meson gnulib_modules="$gnulib_modules configmake" -# -> eliminate usage in some manner -gnulib_modules="$gnulib_modules environ" -# -> GSocket -gnulib_modules="$gnulib_modules fcntl" -# -> conditional build avoid win32 -gnulib_modules="$gnulib_modules fcntl-h" # -> GSocket gnulib_modules="$gnulib_modules getaddrinfo" # -> copy gnuliub win32 impl gnulib_modules="$gnulib_modules getpass" -# -> GSocket -gnulib_modules="$gnulib_modules getpeername" -# -> GSocket -gnulib_modules="$gnulib_modules getsockname" -# -> copy gnulib STRBUFLEN macro -gnulib_modules="$gnulib_modules intprops" -# -> GSocket -gnulib_modules="$gnulib_modules ioctl" # -> Meson gnulib_modules="$gnulib_modules largefile" -# -> GSocket -gnulib_modules="$gnulib_modules listen" # -> custom configure check gnulib_modules="$gnulib_modules localeconv" -# -> Meson -gnulib_modules="$gnulib_modules manywarnings" # -> painful copy gnulib gnulib_modules="$gnulib_modules mgetgroups" # -> GSocket @@ -70,12 +44,8 @@ gnulib_modules="$gnulib_modules net_if" gnulib_modules="$gnulib_modules netdb" # -> GSocket gnulib_modules="$gnulib_modules nonblocking" -# -> Just add -lutil to cli -gnulib_modules="$gnulib_modules openpty" # -> GSocket gnulib_modules="$gnulib_modules passfd" -# -> open code / copy gnulib code -gnulib_modules="$gnulib_modules physmem" # -> open code / conditional comp gnulib_modules="$gnulib_modules pipe-posix" # -> open code / conditional comp @@ -85,19 +55,9 @@ gnulib_modules="$gnulib_modules poll" # -> Meson gnulib_modules="$gnulib_modules posix-shell" # -> open code conditional logic -gnulib_modules="$gnulib_modules pthread_sigmask" -# -> GSocket -gnulib_modules="$gnulib_modules recv" -# -> GSocket -gnulib_modules="$gnulib_modules send" -# -> GSocket -gnulib_modules="$gnulib_modules setsockopt" -# -> open code conditional logic gnulib_modules="$gnulib_modules sigaction" # -> open code conditional logic gnulib_modules="$gnulib_modules sigpipe" -# -> GSocket -gnulib_modules="$gnulib_modules socket" # -> open code conditional or use GIO GFileInfo gnulib_modules="$gnulib_modules stat-time" # -> remove use or open-code it. possibly add to glib @@ -108,20 +68,10 @@ gnulib_modules="$gnulib_modules strtok_r" gnulib_modules="$gnulib_modules sys_stat" # -> remove sys/wait.h include from any win32 code paths gnulib_modules="$gnulib_modules sys_wait" -# -> remove from any win32 code paths -gnulib_modules="$gnulib_modules termios" -# -> GDateTime ? -gnulib_modules="$gnulib_modules time_r" -# -> obsolete - exists on Linux, MacOS >= ?? & FreeBSD >= 6 -gnulib_modules="$gnulib_modules ttyname_r" # -> g_get_os_info in GLib 2.64 but can't use that yet gnulib_modules="$gnulib_modules uname" -# -> G_STATIC_ASSERT -gnulib_modules="$gnulib_modules verify" # -> remove from Win32 code paths gnulib_modules="$gnulib_modules waitpid" -# -> Meson -gnulib_modules="$gnulib_modules warnings" # -> open code impl gnulib_modules="$gnulib_modules wcwidth" diff --git a/m4/virt-manywarnings.m4 b/m4/virt-manywarnings.m4 new file mode 100644 index 0000000000..783620da3a --- /dev/null +++ b/m4/virt-manywarnings.m4 @@ -0,0 +1,339 @@ +# manywarnings.m4 serial 18 +dnl Copyright (C) 2008-2020 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Simon Josefsson + +# gl_MANYWARN_COMPLEMENT(OUTVAR, LISTVAR, REMOVEVAR) +# -------------------------------------------------- +# Copy LISTVAR to OUTVAR except for the entries in REMOVEVAR. +# Elements separated by whitespace. In set logic terms, the function +# does OUTVAR = LISTVAR \ REMOVEVAR. +AC_DEFUN([gl_MANYWARN_COMPLEMENT], +[ + gl_warn_set= + set x $2; shift + for gl_warn_item + do + case " $3 " in + *" $gl_warn_item "*) + ;; + *) + gl_warn_set="$gl_warn_set $gl_warn_item" + ;; + esac + done + $1=$gl_warn_set +]) + +# gl_MANYWARN_ALL_GCC(VARIABLE) +# ----------------------------- +# Add all documented GCC warning parameters to variable VARIABLE. +# Note that you need to test them using gl_WARN_ADD if you want to +# make sure your gcc understands it. +# +# The effects of this macro depend on the current language (_AC_LANG). +AC_DEFUN([gl_MANYWARN_ALL_GCC], +[_AC_LANG_DISPATCH([$0], _AC_LANG, $@)]) + +# Specialization for _AC_LANG = C. +# Use of m4_defun rather than AC_DEFUN works around a bug in autoconf < 2.63b. +m4_defun([gl_MANYWARN_ALL_GCC(C)], +[ + AC_LANG_PUSH([C]) + + dnl First, check for some issues that only occur when combining multiple + dnl gcc warning categories. + AC_REQUIRE([AC_PROG_CC]) + if test -n "$GCC"; then + + dnl Check if -W -Werror -Wno-missing-field-initializers is supported + dnl with the current $CC $CFLAGS $CPPFLAGS. + AC_CACHE_CHECK([whether -Wno-missing-field-initializers is supported], + [gl_cv_cc_nomfi_supported], + [gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror -Wno-missing-field-initializers" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_nomfi_supported=yes], + [gl_cv_cc_nomfi_supported=no]) + CFLAGS="$gl_save_CFLAGS" + ]) + + if test "$gl_cv_cc_nomfi_supported" = yes; then + dnl Now check whether -Wno-missing-field-initializers is needed + dnl for the { 0, } construct. + AC_CACHE_CHECK([whether -Wno-missing-field-initializers is needed], + [gl_cv_cc_nomfi_needed], + [gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[int f (void) + { + typedef struct { int a; int b; } s_t; + s_t s1 = { 0, }; + return s1.b; + } + ]], + [[]])], + [gl_cv_cc_nomfi_needed=no], + [gl_cv_cc_nomfi_needed=yes]) + CFLAGS="$gl_save_CFLAGS" + ]) + fi + + dnl Next, check if -Werror -Wuninitialized is useful with the + dnl user's choice of $CFLAGS; some versions of gcc warn that it + dnl has no effect if -O is not also used + AC_CACHE_CHECK([whether -Wuninitialized is supported], + [gl_cv_cc_uninitialized_supported], + [gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror -Wuninitialized" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_uninitialized_supported=yes], + [gl_cv_cc_uninitialized_supported=no]) + CFLAGS="$gl_save_CFLAGS" + ]) + + fi + + # List all gcc warning categories. + # To compare this list to your installed GCC's, run this Bash command: + # + # comm -3 \ + # <((sed -n 's/^ *\(-[^ 0-9][^ ]*\) .*/\1/p' manywarnings.m4; \ + # awk '/^[^#]/ {print $1}' ../build-aux/gcc-warning.spec) | sort) \ + # <(LC_ALL=C gcc --help=warnings | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort) + + gl_manywarn_set= + for gl_manywarn_item in -fno-common \ + -W \ + -Wabsolute-value \ + -Waddress \ + -Waddress-of-packed-member \ + -Waggressive-loop-optimizations \ + -Wall \ + -Wattribute-warning \ + -Wattributes \ + -Wbad-function-cast \ + -Wbool-compare \ + -Wbool-operation \ + -Wbuiltin-declaration-mismatch \ + -Wbuiltin-macro-redefined \ + -Wcannot-profile \ + -Wcast-align \ + -Wcast-align=strict \ + -Wcast-function-type \ + -Wchar-subscripts \ + -Wclobbered \ + -Wcomment \ + -Wcomments \ + -Wcoverage-mismatch \ + -Wcpp \ + -Wdangling-else \ + -Wdate-time \ + -Wdeprecated \ + -Wdeprecated-declarations \ + -Wdesignated-init \ + -Wdisabled-optimization \ + -Wdiscarded-array-qualifiers \ + -Wdiscarded-qualifiers \ + -Wdiv-by-zero \ + -Wdouble-promotion \ + -Wduplicated-branches \ + -Wduplicated-cond \ + -Wduplicate-decl-specifier \ + -Wempty-body \ + -Wendif-labels \ + -Wenum-compare \ + -Wexpansion-to-defined \ + -Wextra \ + -Wformat-contains-nul \ + -Wformat-extra-args \ + -Wformat-nonliteral \ + -Wformat-security \ + -Wformat-signedness \ + -Wformat-y2k \ + -Wformat-zero-length \ + -Wframe-address \ + -Wfree-nonheap-object \ + -Whsa \ + -Wif-not-aligned \ + -Wignored-attributes \ + -Wignored-qualifiers \ + -Wimplicit \ + -Wimplicit-function-declaration \ + -Wimplicit-int \ + -Wincompatible-pointer-types \ + -Winit-self \ + -Winline \ + -Wint-conversion \ + -Wint-in-bool-context \ + -Wint-to-pointer-cast \ + -Winvalid-memory-model \ + -Winvalid-pch \ + -Wlogical-not-parentheses \ + -Wlogical-op \ + -Wmain \ + -Wmaybe-uninitialized \ + -Wmemset-elt-size \ + -Wmemset-transposed-args \ + -Wmisleading-indentation \ + -Wmissing-attributes \ + -Wmissing-braces \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-include-dirs \ + -Wmissing-parameter-type \ + -Wmissing-profile \ + -Wmissing-prototypes \ + -Wmultichar \ + -Wmultistatement-macros \ + -Wnarrowing \ + -Wnested-externs \ + -Wnonnull \ + -Wnonnull-compare \ + -Wnull-dereference \ + -Wodr \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wopenmp-simd \ + -Woverflow \ + -Woverlength-strings \ + -Woverride-init \ + -Wpacked \ + -Wpacked-bitfield-compat \ + -Wpacked-not-aligned \ + -Wparentheses \ + -Wpointer-arith \ + -Wpointer-compare \ + -Wpointer-sign \ + -Wpointer-to-int-cast \ + -Wpragmas \ + -Wpsabi \ + -Wrestrict \ + -Wreturn-local-addr \ + -Wreturn-type \ + -Wscalar-storage-order \ + -Wsequence-point \ + -Wshadow \ + -Wshift-count-negative \ + -Wshift-count-overflow \ + -Wshift-negative-value \ + -Wsizeof-array-argument \ + -Wsizeof-pointer-div \ + -Wsizeof-pointer-memaccess \ + -Wstack-protector \ + -Wstrict-aliasing \ + -Wstrict-overflow \ + -Wstrict-prototypes \ + -Wstringop-truncation \ + -Wsuggest-attribute=cold \ + -Wsuggest-attribute=const \ + -Wsuggest-attribute=format \ + -Wsuggest-attribute=malloc \ + -Wsuggest-attribute=noreturn \ + -Wsuggest-attribute=pure \ + -Wsuggest-final-methods \ + -Wsuggest-final-types \ + -Wswitch \ + -Wswitch-bool \ + -Wswitch-unreachable \ + -Wsync-nand \ + -Wsystem-headers \ + -Wtautological-compare \ + -Wtrampolines \ + -Wtrigraphs \ + -Wtype-limits \ + -Wuninitialized \ + -Wunknown-pragmas \ + -Wunsafe-loop-optimizations \ + -Wunused \ + -Wunused-but-set-parameter \ + -Wunused-but-set-variable \ + -Wunused-function \ + -Wunused-label \ + -Wunused-local-typedefs \ + -Wunused-macros \ + -Wunused-parameter \ + -Wunused-result \ + -Wunused-value \ + -Wunused-variable \ + -Wvarargs \ + -Wvariadic-macros \ + -Wvector-operation-performance \ + -Wvla \ + -Wvolatile-register-var \ + -Wwrite-strings \ + \ + ; do + gl_manywarn_set="$gl_manywarn_set $gl_manywarn_item" + done + + # gcc --help=warnings outputs an unusual form for these options; list + # them here so that the above 'comm' command doesn't report a false match. + # Would prefer "min (PTRDIFF_MAX, SIZE_MAX)", but it must be a literal. + # Also, AC_COMPUTE_INT requires it to fit in a long; it is 2**63 on + # the only platforms where it does not fit in a long, so make that + # a special case. + AC_MSG_CHECKING([max safe object size]) + AC_COMPUTE_INT([gl_alloc_max], + [LONG_MAX < (PTRDIFF_MAX < (size_t) -1 ? PTRDIFF_MAX : (size_t) -1) + ? -1 + : PTRDIFF_MAX < (size_t) -1 ? (long) PTRDIFF_MAX : (long) (size_t) -1], + [[#include <limits.h> + #include <stddef.h> + #include <stdint.h> + ]], + [gl_alloc_max=2147483647]) + case $gl_alloc_max in + -1) gl_alloc_max=9223372036854775807;; + esac + AC_MSG_RESULT([$gl_alloc_max]) + gl_manywarn_set="$gl_manywarn_set -Walloc-size-larger-than=$gl_alloc_max" + gl_manywarn_set="$gl_manywarn_set -Warray-bounds=2" + gl_manywarn_set="$gl_manywarn_set -Wattribute-alias=2" + gl_manywarn_set="$gl_manywarn_set -Wformat-overflow=2" + gl_manywarn_set="$gl_manywarn_set -Wformat-truncation=2" + gl_manywarn_set="$gl_manywarn_set -Wimplicit-fallthrough=5" + gl_manywarn_set="$gl_manywarn_set -Wnormalized=nfc" + gl_manywarn_set="$gl_manywarn_set -Wshift-overflow=2" + gl_manywarn_set="$gl_manywarn_set -Wstringop-overflow=2" + gl_manywarn_set="$gl_manywarn_set -Wunused-const-variable=2" + gl_manywarn_set="$gl_manywarn_set -Wvla-larger-than=4031" + + # These are needed for older GCC versions. + if test -n "$GCC"; then + case `($CC --version) 2>/dev/null` in + 'gcc (GCC) '[[0-3]].* | \ + 'gcc (GCC) '4.[[0-7]].*) + gl_manywarn_set="$gl_manywarn_set -fdiagnostics-show-option" + gl_manywarn_set="$gl_manywarn_set -funit-at-a-time" + ;; + esac + fi + + # Disable specific options as needed. + if test "$gl_cv_cc_nomfi_needed" = yes; then + gl_manywarn_set="$gl_manywarn_set -Wno-missing-field-initializers" + fi + + if test "$gl_cv_cc_uninitialized_supported" = no; then + gl_manywarn_set="$gl_manywarn_set -Wno-uninitialized" + fi + + $1=$gl_manywarn_set + + AC_LANG_POP([C]) +]) + +# Specialization for _AC_LANG = C++. +# Use of m4_defun rather than AC_DEFUN works around a bug in autoconf < 2.63b. +m4_defun([gl_MANYWARN_ALL_GCC(C++)], +[ + gl_MANYWARN_ALL_GCC_CXX_IMPL([$1]) +]) diff --git a/m4/virt-warnings.m4 b/m4/virt-warnings.m4 new file mode 100644 index 0000000000..d272365f0a --- /dev/null +++ b/m4/virt-warnings.m4 @@ -0,0 +1,115 @@ +# warnings.m4 serial 14 +dnl Copyright (C) 2008-2020 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Simon Josefsson + +# gl_AS_VAR_APPEND(VAR, VALUE) +# ---------------------------- +# Provide the functionality of AS_VAR_APPEND if Autoconf does not have it. +m4_ifdef([AS_VAR_APPEND], +[m4_copy([AS_VAR_APPEND], [gl_AS_VAR_APPEND])], +[m4_define([gl_AS_VAR_APPEND], +[AS_VAR_SET([$1], [AS_VAR_GET([$1])$2])])]) + + +# gl_COMPILER_OPTION_IF(OPTION, [IF-SUPPORTED], [IF-NOT-SUPPORTED], +# [PROGRAM = AC_LANG_PROGRAM()]) +# ----------------------------------------------------------------- +# Check if the compiler supports OPTION when compiling PROGRAM. +# +# The effects of this macro depend on the current language (_AC_LANG). +AC_DEFUN([gl_COMPILER_OPTION_IF], +[ +dnl FIXME: gl_Warn must be used unquoted until we can assume Autoconf +dnl 2.64 or newer. +AS_VAR_PUSHDEF([gl_Warn], [gl_cv_warn_[]_AC_LANG_ABBREV[]_$1])dnl +AS_VAR_PUSHDEF([gl_Flags], [_AC_LANG_PREFIX[]FLAGS])dnl +AS_LITERAL_IF([$1], + [m4_pushdef([gl_Positive], m4_bpatsubst([$1], [^-Wno-], [-W]))], + [gl_positive="$1" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +m4_pushdef([gl_Positive], [$gl_positive])])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler handles $1], m4_defn([gl_Warn]), [ + gl_save_compiler_FLAGS="$gl_Flags" + gl_AS_VAR_APPEND(m4_defn([gl_Flags]), + [" $gl_unknown_warnings_are_errors ]m4_defn([gl_Positive])["]) + AC_LINK_IFELSE([m4_default([$4], [AC_LANG_PROGRAM([])])], + [AS_VAR_SET(gl_Warn, [yes])], + [AS_VAR_SET(gl_Warn, [no])]) + gl_Flags="$gl_save_compiler_FLAGS" +]) +AS_VAR_IF(gl_Warn, [yes], [$2], [$3]) +m4_popdef([gl_Positive])dnl +AS_VAR_POPDEF([gl_Flags])dnl +AS_VAR_POPDEF([gl_Warn])dnl +]) + +# gl_UNKNOWN_WARNINGS_ARE_ERRORS +# ------------------------------ +# Clang doesn't complain about unknown warning options unless one also +# specifies -Wunknown-warning-option -Werror. Detect this. +# +# The effects of this macro depend on the current language (_AC_LANG). +AC_DEFUN([gl_UNKNOWN_WARNINGS_ARE_ERRORS], +[_AC_LANG_DISPATCH([$0], _AC_LANG, $@)]) + +# Specialization for _AC_LANG = C. This macro can be AC_REQUIREd. +# Use of m4_defun rather than AC_DEFUN works around a bug in autoconf < 2.63b. +m4_defun([gl_UNKNOWN_WARNINGS_ARE_ERRORS(C)], +[ + AC_LANG_PUSH([C]) + gl_UNKNOWN_WARNINGS_ARE_ERRORS_IMPL + AC_LANG_POP([C]) +]) + +# Specialization for _AC_LANG = C++. This macro can be AC_REQUIREd. +# Use of m4_defun rather than AC_DEFUN works around a bug in autoconf < 2.63b. +m4_defun([gl_UNKNOWN_WARNINGS_ARE_ERRORS(C++)], +[ + AC_LANG_PUSH([C++]) + gl_UNKNOWN_WARNINGS_ARE_ERRORS_IMPL + AC_LANG_POP([C++]) +]) + +# Specialization for _AC_LANG = Objective C. This macro can be AC_REQUIREd. +# Use of m4_defun rather than AC_DEFUN works around a bug in autoconf < 2.63b. +m4_defun([gl_UNKNOWN_WARNINGS_ARE_ERRORS(Objective C)], +[ + AC_LANG_PUSH([Objective C]) + gl_UNKNOWN_WARNINGS_ARE_ERRORS_IMPL + AC_LANG_POP([Objective C]) +]) + +AC_DEFUN([gl_UNKNOWN_WARNINGS_ARE_ERRORS_IMPL], +[gl_COMPILER_OPTION_IF([-Werror -Wunknown-warning-option], + [gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror'], + [gl_unknown_warnings_are_errors=])]) + +# gl_WARN_ADD(OPTION, [VARIABLE = WARN_CFLAGS/WARN_CXXFLAGS], +# [PROGRAM = AC_LANG_PROGRAM()]) +# ----------------------------------------------------------- +# Adds parameter to WARN_CFLAGS/WARN_CXXFLAGS if the compiler supports it +# when compiling PROGRAM. For example, gl_WARN_ADD([-Wparentheses]). +# +# If VARIABLE is a variable name, AC_SUBST it. +# +# The effects of this macro depend on the current language (_AC_LANG). +AC_DEFUN([gl_WARN_ADD], +[AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS(]_AC_LANG[)]) +gl_COMPILER_OPTION_IF([$1], + [gl_AS_VAR_APPEND(m4_if([$2], [], [[WARN_]_AC_LANG_PREFIX[FLAGS]], [[$2]]), [" $1"])], + [], + [$3]) +m4_ifval([$2], + [AS_LITERAL_IF([$2], [AC_SUBST([$2])])], + [AC_SUBST([WARN_]_AC_LANG_PREFIX[FLAGS])])dnl +]) + +# Local Variables: +# mode: autoconf +# End: -- 2.24.1
participants (2)
-
Daniel P. Berrangé
-
Pavel Hrdina