(1) XDR functions on MinGW come from a library called 'libxdr', not 'librpc'.
(2) To build a DLL under MinGW we need to pass the -no-undefined flag to the linker.
(3) Socket compatibility header file replaces <winsock2.h> inclusion. This just defines a portable 'socket_errno()' function which returns errno in the normal case, or WSAGetLastError() in the Windows case.
(4) Use socket_errno() instead of errno in a few cases (but only when the code can be compiled under Windows, ie. only in the remote client case).
Example -- a dynamically linked virsh.exe (linked to libvirt-0.dll) accessing a remote libvirtd:
$ src/.libs/virsh.exe -c test+tcp://192.168.2.128/default list Id Name State ---------------------------------- 1 test running If you want to compile this under Windows, you will need:(a) MinGW & MSYS (select the "candidate" versions of MinGW tools if you are using Vista or W2K8, since otherwise nothing works because of a known bug).
(b) Install gcc 4 experimental package from MinGW site. It's called gcc-sjlj for reasons which escape me.
(c) Install GnuTLS binary from http://www.gnu.org/software/gnutls/download.html. I'm using GnuTLS Windows binary 1.6.3 and I had to hand-hack the *.la files in that distribution because they contain incorrect paths.
(d) Compile and install latest libxml2 from http://xmlsoft.org/. I'm using 2.6.30.
(e) Compile and install my XDR package for Windows (http://www.annexia.org/tmp/xdr-4.0-mingw5.tar.gz)
(f) ./configure --without-xen --without-qemu --without-sasl --without-libvirtd
(g) make Rich. -- Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/ Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 03798903
Index: configure.in =================================================================== RCS file: /data/cvs/libvirt/configure.in,v retrieving revision 1.116 diff -u -r1.116 configure.in --- configure.in 17 Dec 2007 23:20:13 -0000 1.116 +++ configure.in 4 Jan 2008 12:44:36 -0000 @@ -65,8 +65,8 @@ dnl Availability of various common headers (non-fatal if missing). AC_CHECK_HEADERS([pwd.h paths.h sys/syslimits.h sys/utsname.h sys/wait.h winsock2.h]) -dnl Need -lrpc? (Cygwin needs this) -AC_SEARCH_LIBS(xdrmem_create,rpc) +dnl Need -lrpc or -lxdr? (Cygwin and MinGW resp. need this) +AC_SEARCH_LIBS(xdrmem_create,[rpc xdr]) dnl Do we have rpcgen? AC_PATH_PROG(RPCGEN, rpcgen, no) @@ -650,6 +650,7 @@ CYGWIN_EXTRA_LDFLAGS= CYGWIN_EXTRA_LIBADD= CYGWIN_EXTRA_PYTHON_LIBADD= +MINGW_EXTRA_LDFLAGS= case "$host" in *-*-cygwin*) CYGWIN_EXTRA_LDFLAGS="-no-undefined" @@ -658,10 +659,14 @@ CYGWIN_EXTRA_PYTHON_LIBADD="-L/usr/lib/python${PYTHON_VERSION}/config -lpython${PYTHON_VERSION}" fi ;; + *-*-mingw*) + MINGW_EXTRA_LDFLAGS="-no-undefined" + ;; esac AC_SUBST(CYGWIN_EXTRA_LDFLAGS) AC_SUBST(CYGWIN_EXTRA_LIBADD) AC_SUBST(CYGWIN_EXTRA_PYTHON_LIBADD) +AC_SUBST(MINGW_EXTRA_LDFLAGS) # very annoying rm -f COPYING Index: gnulib/lib/arpa/.cvsignore =================================================================== RCS file: /data/cvs/libvirt/gnulib/lib/arpa/.cvsignore,v retrieving revision 1.1 diff -u -r1.1 .cvsignore --- gnulib/lib/arpa/.cvsignore 7 Dec 2007 14:32:35 -0000 1.1 +++ gnulib/lib/arpa/.cvsignore 4 Jan 2008 12:44:36 -0000 @@ -0,0 +1 @@ +inet.h Index: src/Makefile.am =================================================================== RCS file: /data/cvs/libvirt/src/Makefile.am,v retrieving revision 1.61 diff -u -r1.61 Makefile.am --- src/Makefile.am 17 Dec 2007 10:07:56 -0000 1.61 +++ src/Makefile.am 4 Jan 2008 12:44:37 -0000 @@ -31,6 +31,7 @@ CLIENT_SOURCES = \ libvirt.c internal.h \ gnutls_1_0_compat.h \ + socketcompat.h \ hash.c hash.h \ test.c test.h \ buf.c buf.h \ @@ -68,7 +69,7 @@ libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \ -version-info @LIBVIRT_VERSION_INFO@ \ $(COVERAGE_CFLAGS:-f%=-Wc,-f%) \ - @CYGWIN_EXTRA_LDFLAGS@ + @CYGWIN_EXTRA_LDFLAGS@ @MINGW_EXTRA_LDFLAGS@ libvirt_la_CFLAGS = $(COVERAGE_CFLAGS) bin_PROGRAMS = virsh Index: src/libvirt.c =================================================================== RCS file: /data/cvs/libvirt/src/libvirt.c,v retrieving revision 1.110 diff -u -r1.110 libvirt.c --- src/libvirt.c 15 Dec 2007 17:15:12 -0000 1.110 +++ src/libvirt.c 4 Jan 2008 12:44:39 -0000 @@ -25,7 +25,7 @@ #include <libxml/uri.h> #include "getpass.h" -#if HAVE_WINSOCK2_H +#ifdef HAVE_WINSOCK2_H #include <winsock2.h> #endif Index: src/qparams.c =================================================================== RCS file: /data/cvs/libvirt/src/qparams.c,v retrieving revision 1.1 diff -u -r1.1 qparams.c --- src/qparams.c 17 Dec 2007 10:07:56 -0000 1.1 +++ src/qparams.c 4 Jan 2008 12:44:39 -0000 @@ -20,6 +20,8 @@ * Utility functions to help parse and assemble query strings. */ +#include <config.h> + #include <stdio.h> #include <stdlib.h> #include <stdarg.h> Index: src/remote_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/remote_internal.c,v retrieving revision 1.50 diff -u -r1.50 remote_internal.c --- src/remote_internal.c 2 Jan 2008 22:48:04 -0000 1.50 +++ src/remote_internal.c 4 Jan 2008 12:44:42 -0000 @@ -23,12 +23,14 @@ #include "config.h" +/* Windows socket compatibility functions. */ +#include "socketcompat.h" + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> -#include <errno.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> @@ -46,15 +48,6 @@ #include <paths.h> #endif -#ifndef HAVE_WINSOCK2_H -#include <sys/socket.h> -#include <netdb.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#else -#include <winsock2.h> -#endif - #include <rpc/types.h> #include <rpc/xdr.h> #include <gnutls/gnutls.h> @@ -525,7 +518,7 @@ priv->sock = socket (r->ai_family, SOCK_STREAM, 0); if (priv->sock == -1) { - error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno)); + error (conn, VIR_ERR_SYSTEM_ERROR, strerror (socket_errno ())); continue; } @@ -535,7 +528,7 @@ sizeof no_slow_start); if (connect (priv->sock, r->ai_addr, r->ai_addrlen) == -1) { - error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno)); + error (conn, VIR_ERR_SYSTEM_ERROR, strerror (socket_errno ())); close (priv->sock); continue; } @@ -3036,7 +3029,7 @@ __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "failed to get sock address %d (%s)", - errno, strerror(errno)); + socket_errno (), strerror(socket_errno ())); goto cleanup; } if ((localAddr = addrToString(&sa, salen)) == NULL) @@ -3048,7 +3041,7 @@ __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "failed to get peer address %d (%s)", - errno, strerror(errno)); + socket_errno (), strerror(socket_errno ())); goto cleanup; } if ((remoteAddr = addrToString(&sa, salen)) == NULL) @@ -3601,12 +3594,13 @@ while (len > 0); } else { do { - err = write (priv->sock, p, len); + err = send (priv->sock, p, len, 0); if (err == -1) { - if (errno == EINTR || errno == EAGAIN) + int errno_ = socket_errno (); + if (errno_ == EINTR || errno_ == EAGAIN) continue; error (in_open ? NULL : conn, - VIR_ERR_SYSTEM_ERROR, strerror (errno)); + VIR_ERR_SYSTEM_ERROR, strerror (errno_)); return -1; } len -= err; @@ -3683,12 +3677,13 @@ return err; } else { reread: - err = read (priv->sock, bytes, len); + err = recv (priv->sock, bytes, len, 0); if (err == -1) { - if (errno == EINTR) + int errno_ = socket_errno (); + if (errno_ == EINTR) goto reread; error (in_open ? NULL : conn, - VIR_ERR_SYSTEM_ERROR, strerror (errno)); + VIR_ERR_SYSTEM_ERROR, strerror (errno_)); return -1; } if (err == 0) { Index: src/socketcompat.h =================================================================== RCS file: src/socketcompat.h diff -N src/socketcompat.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/socketcompat.h 4 Jan 2008 12:44:42 -0000 @@ -0,0 +1,60 @@ +/* + * socketcompat.h: Socket compatibility for Windows, making it slightly + * less painful to use. + * + * Use this header under the following circumstances: + * (a) Instead of including any of: <net/if.h>, <netinet/in.h>, + * <sys/socket.h>, <netdb.h>, <netinet/tcp.h>, AND + * (b) The file will be part of what is built on Windows (basically + * just remote client stuff). + * + * You need to use socket_errno() instead of errno to get socket + * errors. + * + * Copyright (C) 2008 Red Hat, Inc. + * + * See COPYING.LIB for the License of this software + * + * Richard W.M. Jones <rjones@xxxxxxxxxx> + */ + +#ifndef __SOCKETCOMPAT_H__ +#define __SOCKETCOMPAT_H__ + +#include <config.h> + +#include <errno.h> + +#ifndef HAVE_WINSOCK2_H /* Unix & Cygwin. */ + +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + +static inline int +socket_errno (void) +{ + return errno; +} + +#else /* MinGW & Win32 */ + +#include <winsock2.h> + +/* Socket functions in Windoze don't set errno. Instead of using errno + * to test for socket errors, call this function to get the errno. + */ +static inline int +socket_errno (void) +{ + return WSAGetLastError (); +} + +/* Compatibility. */ +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ECONNREFUSED WSAECONNREFUSED + +#endif /* HAVE_WINSOCK2_H */ + +#endif /* __WINSOCKWRAPPER_H__ */ Index: src/test.c =================================================================== RCS file: /data/cvs/libvirt/src/test.c,v retrieving revision 1.56 diff -u -r1.56 test.c --- src/test.c 11 Dec 2007 21:57:29 -0000 1.56 +++ src/test.c 4 Jan 2008 12:44:43 -0000 @@ -28,7 +28,6 @@ #include <stdio.h> #include <string.h> #include <sys/time.h> -#include <errno.h> #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xpath.h> @@ -37,12 +36,7 @@ #include <unistd.h> #include <sys/stat.h> -#ifndef HAVE_WINSOCK2_H -#include <net/if.h> -#include <netinet/in.h> -#else -#include <winsock2.h> -#endif +#include "socketcompat.h" #include "internal.h" #include "test.h"
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list