Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 0/5] Port to Windows.
This is an incomplete port to Windows. Currently the server compiles and starts up successfully, but goes into an infinite loop when you connect to it. Nevertheless I think the approach is ready for feedback. This being Windows the changes go quite deep. Rich.
Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 1/5] server: Add general replacements for missing functions using LIBOBJS.
Especially on Windows, some common functions are missing. Use the autoconf LIBOBJS mechanism to replace these functions. This includes replacement functions for: Function names Implementation Origin getdelim, getline general purpose NetBSD under a compatible license openlog, syslog, Win32 written by me vsyslog realpath Win32 written by me strndup general purpose written by me This should do nothing on existing supported platforms. It is only intended in preparation for porting nbdkit to Windows. --- configure.ac | 30 +++++++++++++++ Makefile.am | 1 + lib/getline.h | 50 ++++++++++++++++++++++++ lib/realpath.h | 50 ++++++++++++++++++++++++ lib/strndup.h | 49 ++++++++++++++++++++++++ lib/syslog.h | 67 ++++++++++++++++++++++++++++++++ lib/getdelim.c | 84 +++++++++++++++++++++++++++++++++++++++++ lib/getline.c | 46 ++++++++++++++++++++++ lib/openlog.c | 62 ++++++++++++++++++++++++++++++ lib/realpath.c | 81 +++++++++++++++++++++++++++++++++++++++ lib/strndup.c | 64 +++++++++++++++++++++++++++++++ lib/syslog.c | 62 ++++++++++++++++++++++++++++++ lib/vsyslog.c | 74 ++++++++++++++++++++++++++++++++++++ server/crypto.c | 2 +- server/log-syslog.c | 2 +- server/main.c | 2 + server/utils.c | 2 + .gitignore | 4 ++ lib/Makefile.am | 53 ++++++++++++++++++++++++++ lib/win32/Makefile.am | 46 ++++++++++++++++++++++ lib/win32/nbdkit-cat.mc | 6 +++ server/Makefile.am | 5 ++- 22 files changed, 839 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 7b52abc..c5a23a5 100644 --- a/configure.ac +++ b/configure.ac @@ -90,6 +90,23 @@ if test "x$gcc_warnings" = "xyes"; then AC_SUBST([WARNINGS_CFLAGS]) fi +dnl Is this Windows? +AC_MSG_CHECKING([if the target is Windows]) +AS_CASE([$host_os], + [mingw*], [is_windows=yes], + [is_windows=no] +) +AC_MSG_RESULT([$is_windows]) +AM_CONDITIONAL([IS_WINDOWS],[test "x$is_windows" = "xyes"]) + +AS_IF([test "x$is_windows" = "xyes"],[ + dnl For Windows, look for the mc/windmc utility. + dnl XXX Do we need to check for mc.exe as well? + AC_CHECK_TOOLS([MC],[windmc mc],[no]) + AS_IF([test "x$MC" = "xno"], + [AC_MSG_ERROR([mc/windmc utility must be available when compiling for Windows])]) +]) + dnl On Haiku we must use BSD-compatibility headers to get the endian dnl macros we use. AC_MSG_CHECKING(whether OS-dependent include paths are required) @@ -193,6 +210,17 @@ AC_CHECK_FUNCS([\ get_current_dir_name \ mkostemp]) +dnl Replacement functions that we provide for some platforms. +AC_CONFIG_LIBOBJ_DIR([lib]) +AC_REPLACE_FUNCS([\ + getdelim \ + getline \ + openlog \ + realpath \ + strndup \ + syslog \ + vsyslog]) + dnl Check whether printf("%m") works AC_CACHE_CHECK([whether the printf family supports %m], [nbdkit_cv_func_printf_percent_m], @@ -817,6 +845,8 @@ AC_CONFIG_FILES([Makefile common/sparse/Makefile docs/Makefile include/Makefile + lib/Makefile + lib/win32/Makefile plugins/Makefile plugins/curl/Makefile plugins/data/Makefile diff --git a/Makefile.am b/Makefile.am index 273accb..b551c48 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,7 @@ SUBDIRS = \ docs \ fuzzing \ valgrind \ + lib \ include \ common/include \ server diff --git a/lib/getline.h b/lib/getline.h new file mode 100644 index 0000000..a9e1024 --- /dev/null +++ b/lib/getline.h @@ -0,0 +1,50 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NBDKIT_GETLINE_H +#define NBDKIT_GETLINE_H + +#include <config.h> + +#ifdef HAVE_GETLINE + +#include <stdio.h> + +#else + +ssize_t getline (char **lineptr, size_t *n, FILE *stream); +ssize_t getdelim (char **lineptr, size_t *n, int delim, FILE *stream); + +#endif + +#endif /* NBDKIT_GETLINE_H */ diff --git a/lib/realpath.h b/lib/realpath.h new file mode 100644 index 0000000..14fee81 --- /dev/null +++ b/lib/realpath.h @@ -0,0 +1,50 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NBDKIT_REALPATH_H +#define NBDKIT_REALPATH_H + +#include <config.h> + +#ifdef HAVE_REALPATH + +#include <limits.h> +#include <stdlib.h> + +#else + +char *realpath (const char *path, char *out); + +#endif + +#endif /* NBDKIT_REALPATH_H */ diff --git a/lib/strndup.h b/lib/strndup.h new file mode 100644 index 0000000..464ce95 --- /dev/null +++ b/lib/strndup.h @@ -0,0 +1,49 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NBDKIT_STRNDUP_H +#define NBDKIT_STRNDUP_H + +#include <config.h> + +#ifdef HAVE_STRNDUP + +#include <string.h> + +#else + +char *strndup(const char *s, size_t n); + +#endif + +#endif /* NBDKIT_STRNDUP_H */ diff --git a/lib/syslog.h b/lib/syslog.h new file mode 100644 index 0000000..e4d7667 --- /dev/null +++ b/lib/syslog.h @@ -0,0 +1,67 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Replacement for syslog for platforms which lack it. Note this only + * implements "just enough syslog" for nbdkit. It's not a general + * replacement. + */ + +#ifndef NBDKIT_SYSLOG_H +#define NBDKIT_SYSLOG_H + +#include <config.h> + +#ifdef HAVE_SYSLOG_H + +#include_next <syslog.h> + +#else + +#include <stdarg.h> + +/* Since the replacement function ignores the priority field, we only + * need to define these to any integer. + */ +#define LOG_PID 0 +#define LOG_ERR 0 +#define LOG_DAEMON 0 + +extern void openlog (const char *ident, int option, int facility); +extern void syslog (int pri, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern void vsyslog (int pri, const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); + +#endif /* !HAVE_SYSLOG_H */ + +#endif /* NBDKIT_SYSLOG_H */ diff --git a/lib/getdelim.c b/lib/getdelim.c new file mode 100644 index 0000000..97421cb --- /dev/null +++ b/lib/getdelim.c @@ -0,0 +1,84 @@ +/* $NetBSD: getdelim.c,v 1.2 2015/12/25 20:12:46 joerg Exp $ */ +/* NetBSD-src: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#ifndef HAVE_GETDELIM + +#include "getline.h" + +ssize_t +getdelim (char **buf, size_t *bufsiz, int delimiter, FILE *fp) +{ + char *ptr, *eptr; + + if (*buf == NULL || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = malloc (*bufsiz)) == NULL) + return -1; + } + + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc (fp); + if (c == -1) { + if (feof (fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = realloc (*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } +} + +#endif diff --git a/lib/getline.c b/lib/getline.c new file mode 100644 index 0000000..e9caf49 --- /dev/null +++ b/lib/getline.c @@ -0,0 +1,46 @@ +/* $NetBSD: getline.c,v 1.2 2015/12/25 20:12:46 joerg Exp $ */ +/* NetBSD-src: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <config.h> +#include <stdio.h> + +#ifndef HAVE_GETLINE + +#include "getline.h" + +ssize_t +getline (char **buf, size_t *bufsiz, FILE *fp) +{ + return getdelim (buf, bufsiz, '\n', fp); +} + +#endif diff --git a/lib/openlog.c b/lib/openlog.c new file mode 100644 index 0000000..2f60165 --- /dev/null +++ b/lib/openlog.c @@ -0,0 +1,62 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifndef HAVE_OPENLOG_H + +#include "syslog.h" + +#ifdef WIN32 + +/* Replacement openlog for Win32. */ + +#include <windows.h> + +HANDLE event_source = INVALID_HANDLE_VALUE; + +void +openlog (const char *ident, int option, int facility) +{ + event_source = RegisterEventSource (NULL, ident); +} + +#else /* !WIN32 */ +#error "no replacement openlog is available on this platform" +#endif + +#endif /* !HAVE_SYSLOG_H */ diff --git a/lib/realpath.c b/lib/realpath.c new file mode 100644 index 0000000..622ee7e --- /dev/null +++ b/lib/realpath.c @@ -0,0 +1,81 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Replacement for realpath for platforms which lack this function. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifndef HAVE_REALPATH + +#include "realpath.h" + +#ifdef WIN32 + +/* Replacement realpath for Win32. + * + * Note this is not thread-safe, but should be fine for all the + * uses in the server and ordinary plugins. + */ + +#include <windows.h> + +char * +realpath (const char *path, char *out) +{ + TCHAR buf[MAX_PATH]; + int r; + + r = GetFullPathNameA (path, MAX_PATH, buf, NULL); + if (r == 0) { + errno = GetLastError (); + return NULL; + } + + out = malloc (r + 1); + if (out == NULL) + return NULL; + memcpy (out, buf, r); + out[r] = '\0'; + + return out; +} + +#else /* !WIN32 */ +#error "no replacement realpath is available on this platform" +#endif + +#endif /* !HAVE_REALPATH */ diff --git a/lib/strndup.c b/lib/strndup.c new file mode 100644 index 0000000..de1c27c --- /dev/null +++ b/lib/strndup.c @@ -0,0 +1,64 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Replacement for strndup for platforms which lack this function. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef HAVE_STRNDUP + +#include "strndup.h" + +char * +strndup(const char *s, size_t n) +{ + size_t len = strlen (s); + char *ret; + + if (len > n) + len = n; + + ret = malloc (len+1); + if (ret == NULL) + return NULL; + memcpy (ret, s, len); + ret[len] = '\0'; + + return ret; +} + +#endif /* !HAVE_STRNDUP */ diff --git a/lib/syslog.c b/lib/syslog.c new file mode 100644 index 0000000..6f41cbd --- /dev/null +++ b/lib/syslog.c @@ -0,0 +1,62 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifndef HAVE_SYSLOG_H + +#include "syslog.h" + +#ifdef WIN32 + +/* Replacement syslog for Win32. */ + +void +syslog (int pri, const char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + vsyslog (pri, fmt, args); + va_end (args); +} + +#else /* !WIN32 */ +#error "no replacement syslog is available on this platform" +#endif + +#endif /* !HAVE_SYSLOG_H */ diff --git a/lib/vsyslog.c b/lib/vsyslog.c new file mode 100644 index 0000000..331aba0 --- /dev/null +++ b/lib/vsyslog.c @@ -0,0 +1,74 @@ +/* nbdkit + * Copyright (C) 2019 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifndef HAVE_SYSLOG_H + +#include "syslog.h" + +#ifdef WIN32 + +/* Replacement vsyslog for Win32. */ + +#include <windows.h> + +#include "win32/nbdkit-cat.h" + +extern HANDLE event_source; + +void +vsyslog (int pri, const char *fmt, va_list args) +{ + char *str; + const char *strs[1]; + + if (vasprintf (&str, fmt, args) == -1) + return; + strs[0] = str; + + ReportEventA (event_source, EVENTLOG_ERROR_TYPE, 0, + NBDKIT_SYSLOG_ERROR, NULL, 1, 0, strs, NULL); + + free (str); +} + +#else /* !WIN32 */ +#error "no replacement vsyslog is available on this platform" +#endif + +#endif /* !HAVE_SYSLOG_H */ diff --git a/server/crypto.c b/server/crypto.c index 4638a69..711e929 100644 --- a/server/crypto.c +++ b/server/crypto.c @@ -42,12 +42,12 @@ #include <string.h> #include <unistd.h> #include <fcntl.h> -#include <limits.h> #include <errno.h> #include <sys/types.h> #include <assert.h> #include "internal.h" +#include "realpath.h" #ifdef HAVE_GNUTLS diff --git a/server/log-syslog.c b/server/log-syslog.c index 611ed04..0c58b75 100644 --- a/server/log-syslog.c +++ b/server/log-syslog.c @@ -38,9 +38,9 @@ #include <stdarg.h> #include <string.h> #include <errno.h> -#include <syslog.h> #include "internal.h" +#include "syslog.h" /* Tempted to use LOG_FTP instead of LOG_DAEMON! */ static const int PRIORITY = LOG_DAEMON|LOG_ERR; diff --git a/server/main.c b/server/main.c index 130bf11..5ba4d0d 100644 --- a/server/main.c +++ b/server/main.c @@ -56,6 +56,8 @@ #include <dlfcn.h> #include "internal.h" +#include "strndup.h" +#include "syslog.h" #include "options.h" #include "exit-with-parent.h" diff --git a/server/utils.c b/server/utils.c index 18011fd..3799490 100644 --- a/server/utils.c +++ b/server/utils.c @@ -47,6 +47,8 @@ #include "get-current-dir-name.h" #include "internal.h" +#include "realpath.h" +#include "getline.h" char * nbdkit_absolute_path (const char *path) diff --git a/.gitignore b/.gitignore index 5eb5d59..34a5657 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,10 @@ Makefile.in /html/*.html /INSTALL /install-sh +/lib/libcompat.a +/lib/win32/MSG00001.bin +/lib/win32/nbdkit-cat.h +/lib/win32/nbdkit-cat.rc /libtool /ltmain.sh /missing diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..5051099 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,53 @@ +# nbdkit +# Copyright (C) 2019 Red Hat Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +SUBDIRS = win32 + +noinst_LTLIBRARIES = libcompat.la +# sources should be empty +libcompat_la_SOURCES +libcompat_la_LIBADD = $(LTLIBOBJS) + +EXTRA_DIST = \ + getdelim.c \ + getline.c \ + getline.h \ + openlog.c \ + realpath.c \ + realpath.h \ + strndup.c \ + strndup.h \ + syslog.c \ + syslog.h \ + vsyslog.c diff --git a/lib/win32/Makefile.am b/lib/win32/Makefile.am new file mode 100644 index 0000000..f4ec025 --- /dev/null +++ b/lib/win32/Makefile.am @@ -0,0 +1,46 @@ +# nbdkit +# Copyright (C) 2019 Red Hat Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +EXTRA_DIST = nbdkit-cat.mc + +if IS_WINDOWS + +# Build the message catalog. +noinst_DATA = MSG00001.bin nbdkit-cat.h nbdkit-cat.rc + +$(noinst_DATA): nbdkit-cat.mc + rm -f $@ + $(MC) $< + +endif diff --git a/lib/win32/nbdkit-cat.mc b/lib/win32/nbdkit-cat.mc new file mode 100644 index 0000000..687a835 --- /dev/null +++ b/lib/win32/nbdkit-cat.mc @@ -0,0 +1,6 @@ +MessageId=1 +Severity=Error +SymbolicName=NBDKIT_SYSLOG_ERROR +Language=English +%1 +. diff --git a/server/Makefile.am b/server/Makefile.am index 9469530..80efef5 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -67,6 +67,7 @@ nbdkit_CPPFLAGS = \ -Dfilterdir=\"$(filterdir)\" \ -Dsbindir=\"$(sbindir)\" \ -Dsysconfdir=\"$(sysconfdir)\" \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include nbdkit_CFLAGS = \ @@ -76,7 +77,8 @@ nbdkit_CFLAGS = \ $(VALGRIND_CFLAGS) nbdkit_LDADD = \ $(GNUTLS_LIBS) \ - $(DL_LIBS) + $(DL_LIBS) \ + ../lib/libcompat.la nbdkit_LDFLAGS = \ $(PTHREAD_LIBS) \ $(DL_LDFLAGS) @@ -125,6 +127,7 @@ test_utils_SOURCES = \ utils.c \ cleanup.c test_utils_CPPFLAGS = \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include test_utils_CFLAGS = $(WARNINGS_CFLAGS) $(VALGRIND_CFLAGS) -- 2.20.1
Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 2/5] lib: Use replacement strategy for get_current_dir_name.
This is really a replacement for a missing platform function, so use the same LIBOBJS mechanism to replace it. --- configure.ac | 2 +- lib/get_current_dir_name.h | 49 +++++++++++++++++++ .../get_current_dir_name.c | 10 ++-- .../include => lib}/test-current-dir-name.c | 2 +- plugins/floppy/virtual-floppy.c | 4 +- server/utils.c | 3 +- .gitignore | 2 +- common/include/Makefile.am | 6 --- lib/Makefile.am | 10 ++++ plugins/floppy/Makefile.am | 1 + 10 files changed, 70 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index c5a23a5..8c2d9c0 100644 --- a/configure.ac +++ b/configure.ac @@ -207,12 +207,12 @@ AC_CHECK_HEADERS([\ dnl Check for functions in libc, all optional. AC_CHECK_FUNCS([\ fdatasync \ - get_current_dir_name \ mkostemp]) dnl Replacement functions that we provide for some platforms. AC_CONFIG_LIBOBJ_DIR([lib]) AC_REPLACE_FUNCS([\ + get_current_dir_name \ getdelim \ getline \ openlog \ diff --git a/lib/get_current_dir_name.h b/lib/get_current_dir_name.h new file mode 100644 index 0000000..95d4d47 --- /dev/null +++ b/lib/get_current_dir_name.h @@ -0,0 +1,49 @@ +/* nbdkit + * Copyright (C) 2018 Red Hat Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NBDKIT_GET_CURRENT_DIR_NAME_H +#define NBDKIT_GET_CURRENT_DIR_NAME_H + +#include <config.h> + +#ifdef HAVE_GET_CURRENT_DIR_NAME + +#include <unistd.h> + +#else + +extern char *get_current_dir_name (void); + +#endif + +#endif /* NBDKIT_GET_CURRENT_DIR_NAME_H */ diff --git a/common/include/get-current-dir-name.h b/lib/get_current_dir_name.c similarity index 93% rename from common/include/get-current-dir-name.h rename to lib/get_current_dir_name.c index d99c1ad..5c018e2 100644 --- a/common/include/get-current-dir-name.h +++ b/lib/get_current_dir_name.c @@ -33,9 +33,6 @@ /* Implement get_current_dir_name(3) on platforms which don't have it. */ -#ifndef NBDKIT_GET_CURRENT_DIR_NAME_H -#define NBDKIT_GET_CURRENT_DIR_NAME_H - #include <config.h> #ifndef HAVE_GET_CURRENT_DIR_NAME @@ -44,7 +41,9 @@ #include <unistd.h> #include <limits.h> -static inline char * +#include "get_current_dir_name.h" + +char * get_current_dir_name (void) { char *ret; @@ -57,6 +56,5 @@ get_current_dir_name (void) return NULL; return realloc (ret, strlen (ret) + 1); } -#endif -#endif /* NBDKIT_GET_CURRENT_DIR_NAME_H */ +#endif /* !HAVE_GET_CURRENT_DIR_NAME */ diff --git a/common/include/test-current-dir-name.c b/lib/test-current-dir-name.c similarity index 98% rename from common/include/test-current-dir-name.c rename to lib/test-current-dir-name.c index e2415dd..dfcba76 100644 --- a/common/include/test-current-dir-name.c +++ b/lib/test-current-dir-name.c @@ -40,7 +40,7 @@ #include <unistd.h> #include <assert.h> -#include "get-current-dir-name.h" +#include "get_current_dir_name.h" int main (void) diff --git a/plugins/floppy/virtual-floppy.c b/plugins/floppy/virtual-floppy.c index 5b52e0e..9313767 100644 --- a/plugins/floppy/virtual-floppy.c +++ b/plugins/floppy/virtual-floppy.c @@ -48,12 +48,12 @@ #include <nbdkit-plugin.h> -#include "get-current-dir-name.h" - #include "byte-swapping.h" #include "regions.h" #include "rounding.h" +#include "get_current_dir_name.h" + #include "virtual-floppy.h" /* This is the Windows 98 OEM name, and some sites recommend using it diff --git a/server/utils.c b/server/utils.c index 3799490..d67ec43 100644 --- a/server/utils.c +++ b/server/utils.c @@ -44,11 +44,10 @@ #include <termios.h> #include <errno.h> -#include "get-current-dir-name.h" - #include "internal.h" #include "realpath.h" #include "getline.h" +#include "get_current_dir_name.h" char * nbdkit_absolute_path (const char *path) diff --git a/.gitignore b/.gitignore index 34a5657..35561e9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,6 @@ Makefile.in /autom4te.cache /common/bitmap/test-bitmap /common/include/test-byte-swapping -/common/include/test-current-dir-name /common/include/test-isaligned /common/include/test-ispowerof2 /common/include/test-iszero @@ -48,6 +47,7 @@ Makefile.in /INSTALL /install-sh /lib/libcompat.a +/lib/test-current-dir-name /lib/win32/MSG00001.bin /lib/win32/nbdkit-cat.h /lib/win32/nbdkit-cat.rc diff --git a/common/include/Makefile.am b/common/include/Makefile.am index 6bb2285..aa0ca52 100644 --- a/common/include/Makefile.am +++ b/common/include/Makefile.am @@ -37,7 +37,6 @@ include $(top_srcdir)/common-rules.mk EXTRA_DIST = \ byte-swapping.h \ exit-with-parent.h \ - get-current-dir-name.h \ isaligned.h \ ispowerof2.h \ iszero.h \ @@ -50,7 +49,6 @@ EXTRA_DIST = \ TESTS = \ test-byte-swapping \ - test-current-dir-name \ test-isaligned \ test-ispowerof2 \ test-iszero \ @@ -62,10 +60,6 @@ test_byte_swapping_SOURCES = test-byte-swapping.c byte-swapping.h test_byte_swapping_CPPFLAGS = -I$(srcdir) test_byte_swapping_CFLAGS = $(WARNINGS_CFLAGS) -test_current_dir_name_SOURCES = test-current-dir-name.c get-current-dir-name.h -test_current_dir_name_CPPFLAGS = -I$(srcdir) -test_current_dir_name_CFLAGS = $(WARNINGS_CFLAGS) - test_isaligned_SOURCES = test-isaligned.c isaligned.h test_isaligned_CPPFLAGS = -I$(srcdir) test_isaligned_CFLAGS = $(WARNINGS_CFLAGS) diff --git a/lib/Makefile.am b/lib/Makefile.am index 5051099..5d73ac3 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -40,6 +40,8 @@ libcompat_la_SOURCES libcompat_la_LIBADD = $(LTLIBOBJS) EXTRA_DIST = \ + get_current_dir_name.c \ + get_current_dir_name.h \ getdelim.c \ getline.c \ getline.h \ @@ -51,3 +53,11 @@ EXTRA_DIST = \ syslog.c \ syslog.h \ vsyslog.c + +TESTS = \ + test-current-dir-name +check_PROGRAMS = $(TESTS) + +test_current_dir_name_SOURCES = test-current-dir-name.c get_current_dir_name.h +test_current_dir_name_CPPFLAGS = -I$(srcdir) +test_current_dir_name_CFLAGS = $(WARNINGS_CFLAGS) diff --git a/plugins/floppy/Makefile.am b/plugins/floppy/Makefile.am index 499e2e9..202cebd 100644 --- a/plugins/floppy/Makefile.am +++ b/plugins/floppy/Makefile.am @@ -46,6 +46,7 @@ nbdkit_floppy_plugin_la_SOURCES = \ $(top_srcdir)/include/nbdkit-plugin.h nbdkit_floppy_plugin_la_CPPFLAGS = \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/regions \ -- 2.20.1
Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 3/5] server: sockets: Refactor accept_incoming_connections.
This is a simple refactoring of the function, allowing us to reimplement the inner loop for Windows in a future commit. Note that I made explicit that fds[nr_socks] is used for the quit_fd entry, previously this was implicit which was somewhat confusing. --- server/sockets.c | 64 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/server/sockets.c b/server/sockets.c index d92236f..cc15c5e 100644 --- a/server/sockets.c +++ b/server/sockets.c @@ -314,39 +314,55 @@ accept_connection (int listen_sock) */ } -void -accept_incoming_connections (int *socks, size_t nr_socks) +/* Check the list of sockets plus quit_fd until a POLLIN event occurs + * on any of them. + * + * If POLLIN occurs on quit_fd do nothing except returning early + * (don't call accept_connection in this case). + * + * If POLLIN occurs on one of the sockets, call + * accept_connection (socks[i]) on each of them. + */ +static void +check_sockets_and_quit_fd (int *socks, size_t nr_socks) { struct pollfd fds[nr_socks + 1]; size_t i; int r; - while (!quit) { - for (i = 0; i < nr_socks; ++i) { - fds[i].fd = socks[i]; - fds[i].events = POLLIN; - fds[i].revents = 0; - } - fds[i].fd = quit_fd; + for (i = 0; i < nr_socks; ++i) { + fds[i].fd = socks[i]; fds[i].events = POLLIN; fds[i].revents = 0; + } + fds[nr_socks].fd = quit_fd; + fds[nr_socks].events = POLLIN; + fds[nr_socks].revents = 0; - r = poll (fds, nr_socks + 1, -1); - if (r == -1) { - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("poll"); - exit (EXIT_FAILURE); - } + r = poll (fds, nr_socks + 1, -1); + if (r == -1) { + if (errno == EINTR || errno == EAGAIN) + return; + perror ("poll"); + exit (EXIT_FAILURE); + } - /* We don't even have to read quit_fd - just knowing that it has data - * means the signal handler ran, so we are ready to quit the loop. */ + /* We don't even have to read quit_fd - just knowing that it has + * data means the signal handler ran, so we are ready to quit the + * loop. + */ + if (fds[nr_socks].revents & POLLIN) + return; + + for (i = 0; i < nr_socks; ++i) { if (fds[i].revents & POLLIN) - continue; - - for (i = 0; i < nr_socks; ++i) { - if (fds[i].revents & POLLIN) - accept_connection (fds[i].fd); - } + accept_connection (socks[i]); } } + +void +accept_incoming_connections (int *socks, size_t nr_socks) +{ + while (!quit) + check_sockets_and_quit_fd (socks, nr_socks); +} -- 2.20.1
Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 4/5] server: Port to Windows using mingw-w64.
This allows nbdkit to be cross-compiled for Windows (from Linux). On Fedora[1] you would use the commands below: sudo dnf install mingw64-gcc mingw64-dlfcn \ mingw64-gnutls mingw64-xz mingw64-zlib mingw64-configure --disable-plugins make This results in a Windows binary which can be run on Windows or on Linux under Wine. It also probably allows nbdkit to be compiled on Windows natively using the mingw-w64 port of GCC, but I did not test that. There are several limitations compared to running nbdkit on a real server, see ‘TODO’ for the complete list. [1] Note that mingw64-configure is a Fedora-specific script which runs ./configure with extra parameters to make cross-compilation for Windows work. You can add other configure parameters to the command or if you're not using Fedora then use ‘./configure --host=...’ instead. --- configure.ac | 21 ++- common/include/byte-swapping.h | 7 + include/nbdkit-common.h | 24 +-- include/nbdkit-plugin.h | 2 +- server/internal.h | 47 ++++++ server/crypto.c | 7 +- server/log-syslog.c | 5 + server/main.c | 259 ++++++++++++++++++++++++--------- server/quit.c | 56 +++++++ server/sockets.c | 80 +++++++++- server/utils.c | 80 ++++++++-- .gitignore | 4 + TODO | 21 +++ server/Makefile.am | 17 ++- server/nbdkit.def | 47 ++++++ server/nbdkit.syms | 2 + tests/Makefile.am | 48 +++++- 17 files changed, 626 insertions(+), 101 deletions(-) diff --git a/configure.ac b/configure.ac index 8c2d9c0..f618324 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,14 @@ AS_IF([test "x$is_windows" = "xyes"],[ AC_CHECK_TOOLS([MC],[windmc mc],[no]) AS_IF([test "x$MC" = "xno"], [AC_MSG_ERROR([mc/windmc utility must be available when compiling for Windows])]) + + dnl On Windows look for dlltool. + AC_CHECK_TOOLS([DLLTOOL],[dlltool],[no]) + AS_IF([test "x$DLLTOOL" = "xno"], + [AC_MSG_ERROR([dlltool utility must be available when compiling for Windows])]) + + dnl On Windows we require winsock2. + AC_CHECK_LIB([ws2_32], [socket]) ]) dnl On Haiku we must use BSD-compatibility headers to get the endian @@ -199,10 +207,21 @@ AC_CHECK_HEADERS([\ alloca.h \ byteswap.h \ endian.h \ + grp.h \ + netdb.h \ + poll.h \ + pwd.h \ selinux/selinux.h \ + syslog.h \ sys/endian.h \ sys/prctl.h \ - sys/procctl.h]) + sys/procctl.h \ + sys/socket.h \ + sys/un.h \ + sys/wait.h \ + termios.h \ + windows.h \ + ws2tcpip.h]) dnl Check for functions in libc, all optional. AC_CHECK_FUNCS([\ diff --git a/common/include/byte-swapping.h b/common/include/byte-swapping.h index c0831ec..a7ec78b 100644 --- a/common/include/byte-swapping.h +++ b/common/include/byte-swapping.h @@ -59,6 +59,13 @@ #include <sys/endian.h> #endif +#ifdef WIN32 +#include <stdlib.h> +#define __bswap_16 _byteswap_ushort +#define __bswap_32 _byteswap_ulong +#define __bswap_64 _byteswap_uint64 +#endif + #ifndef htobe32 # if __BYTE_ORDER == __LITTLE_ENDIAN # define htobe16(x) __bswap_16 (x) diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h index cb9954e..7d68cd4 100644 --- a/include/nbdkit-common.h +++ b/include/nbdkit-common.h @@ -53,6 +53,12 @@ extern "C" { #define ATTRIBUTE_FORMAT_PRINTF(fmtpos, argpos) #endif +#ifdef WIN32 +#define NBDKIT_DLLEXPORT __declspec(dllexport) +#else +#define NBDKIT_DLLEXPORT +#endif + #define NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS 0 #define NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS 1 #define NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS 2 @@ -65,16 +71,16 @@ extern "C" { #define NBDKIT_FUA_EMULATE 1 #define NBDKIT_FUA_NATIVE 2 -extern void nbdkit_error (const char *msg, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); -extern void nbdkit_verror (const char *msg, va_list args); -extern void nbdkit_debug (const char *msg, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); -extern void nbdkit_vdebug (const char *msg, va_list args); +extern NBDKIT_DLLEXPORT void nbdkit_error (const char *msg, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); +extern NBDKIT_DLLEXPORT void nbdkit_verror (const char *msg, va_list args); +extern NBDKIT_DLLEXPORT void nbdkit_debug (const char *msg, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); +extern NBDKIT_DLLEXPORT void nbdkit_vdebug (const char *msg, va_list args); -extern char *nbdkit_absolute_path (const char *path); -extern int64_t nbdkit_parse_size (const char *str); -extern int nbdkit_parse_bool (const char *str); -extern int nbdkit_read_password (const char *value, char **password); -extern char *nbdkit_realpath (const char *path); +extern NBDKIT_DLLEXPORT char *nbdkit_absolute_path (const char *path); +extern NBDKIT_DLLEXPORT int64_t nbdkit_parse_size (const char *str); +extern NBDKIT_DLLEXPORT int nbdkit_parse_bool (const char *str); +extern NBDKIT_DLLEXPORT int nbdkit_read_password (const char *value, char **password); +extern NBDKIT_DLLEXPORT char *nbdkit_realpath (const char *path); /* A static non-NULL pointer which can be used when you don't need a * per-connection handle. diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h index d43b2f5..55ccc23 100644 --- a/include/nbdkit-plugin.h +++ b/include/nbdkit-plugin.h @@ -127,7 +127,7 @@ struct nbdkit_plugin { int (*can_multi_conn) (void *handle); }; -extern void nbdkit_set_error (int err); +extern NBDKIT_DLLEXPORT void nbdkit_set_error (int err); #define NBDKIT_REGISTER_PLUGIN(plugin) \ NBDKIT_CXX_LANG_C \ diff --git a/server/internal.h b/server/internal.h index 21bb4fa..24464b9 100644 --- a/server/internal.h +++ b/server/internal.h @@ -37,7 +37,20 @@ #include <stdbool.h> #include <stddef.h> #include <stdarg.h> +#include <errno.h> + +#ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> +#endif + +#ifdef HAVE_WS2TCPIP_H +#include <ws2tcpip.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif + #include <pthread.h> #define NBDKIT_API_VERSION 2 @@ -58,6 +71,36 @@ #define SOCK_CLOEXEC 0 #endif +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +#ifdef WIN32 + +/* Windows <errno.h> lacks certain errnos, so replace them here as + * best we can. + */ +#ifndef EBADMSG +#define EBADMSG EPROTO +#endif +#ifndef ESHUTDOWN +#define ESHUTDOWN ECONNABORTED +#endif + +/* Windows doesn't have flockfile/funlockfile so messages may get + * split over threads. + */ +#define flockfile(fp) +#define funlockfile(fp) + +#endif /* WIN32 */ + +#ifndef WIN32 +#define HAVE_UNIX_SOCKETS 1 +#else +#undef HAVE_UNIX_SOCKETS +#endif + #if HAVE_VALGRIND # include <valgrind.h> /* http://valgrind.org/docs/manual/faq.html#faq.unhelpful */ @@ -113,7 +156,11 @@ extern struct backend *backend; /* quit.c */ extern volatile int quit; +#ifndef WIN32 extern int quit_fd; +#else +extern HANDLE quit_fd; +#endif extern void set_up_quit_pipe (void); extern void handle_quit (int sig); extern void set_quit (void); diff --git a/server/crypto.c b/server/crypto.c index 711e929..3e73ff1 100644 --- a/server/crypto.c +++ b/server/crypto.c @@ -162,7 +162,12 @@ start_certificates (void) const char *home; CLEANUP_FREE char *path = NULL; - if (geteuid () != 0) { +#ifndef WIN32 +#define RUNNING_AS_NON_ROOT_FOR_CERTIFICATES_DIR (geteuid () != 0) +#else +#define RUNNING_AS_NON_ROOT_FOR_CERTIFICATES_DIR 0 +#endif + if (RUNNING_AS_NON_ROOT_FOR_CERTIFICATES_DIR) { home = getenv ("HOME"); if (home) { if (asprintf (&path, "%s/.pki/%s", home, PACKAGE_NAME) == -1) { diff --git a/server/log-syslog.c b/server/log-syslog.c index 0c58b75..fbaa802 100644 --- a/server/log-syslog.c +++ b/server/log-syslog.c @@ -42,6 +42,11 @@ #include "internal.h" #include "syslog.h" +#ifdef WIN32 +/* The Windows API doesn't have open_memstream, so hack this. */ +#define open_memstream(m,n) NULL +#endif + /* Tempted to use LOG_FTP instead of LOG_DAEMON! */ static const int PRIORITY = LOG_DAEMON|LOG_ERR; diff --git a/server/main.c b/server/main.c index 5ba4d0d..475ba68 100644 --- a/server/main.c +++ b/server/main.c @@ -42,14 +42,22 @@ #include <signal.h> #include <getopt.h> #include <limits.h> -#include <pwd.h> -#include <grp.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/wait.h> #include <errno.h> #include <assert.h> -#include <syslog.h> + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_GRP_H +#include <grp.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif #include <pthread.h> @@ -63,7 +71,6 @@ #define FIRST_SOCKET_ACTIVATION_FD 3 /* defined by systemd ABI */ -static char *make_random_fifo (void); static struct backend *open_plugin_so (size_t i, const char *filename, int short_name); static struct backend *open_filter_so (struct backend *next, size_t i, const char *filename, int short_name); static void start_serving (void); @@ -72,8 +79,6 @@ static void run_command (void); static void change_user (void); static void write_pidfile (void); static void fork_into_background (void); -static uid_t parseuser (const char *); -static gid_t parsegroup (const char *); static unsigned int get_socket_activation (void); static int is_config_key (const char *key, size_t len); @@ -106,8 +111,12 @@ bool forked_into_background; /* The currently loaded plugin. */ struct backend *backend; +#ifdef HAVE_UNIX_SOCKETS +static char *make_random_fifo (void); static char *random_fifo_dir = NULL; static char *random_fifo = NULL; +#endif +static void free_random_fifo (void); static void usage (void) @@ -167,6 +176,17 @@ main (int argc, char *argv[]) size_t i; const char *magic_config_key; +#ifdef WIN32 + /* Initialize winsock. 2.2 is the current & latest version. */ + WSADATA wsaData; + int wsaresult; + wsaresult = WSAStartup (MAKEWORD (2, 2), &wsaData); + if (wsaresult != 0) { + fprintf (stderr, "WSAStartup: failed with error %d\n", wsaresult); + exit (EXIT_FAILURE); + } +#endif + threadlocal_init (); /* The default setting for TLS depends on whether we were @@ -407,6 +427,7 @@ main (int argc, char *argv[]) } break; +#ifdef HAVE_UNIX_SOCKETS case 'U': if (socket_activation) { fprintf (stderr, "%s: cannot use socket activation with -U flag\n", @@ -421,6 +442,14 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); break; +#else /* !HAVE_UNIX_SOCKETS */ + case 'U': + fprintf (stderr, "%s: -U option: Unix domain sockets " + "are not supported on this platform\n", + program_name); + exit (EXIT_FAILURE); +#endif + case 'u': user = optarg; break; @@ -670,21 +699,15 @@ main (int argc, char *argv[]) free (unixsocket); free (pidfile); - if (random_fifo) { - unlink (random_fifo); - free (random_fifo); - } - - if (random_fifo_dir) { - rmdir (random_fifo_dir); - free (random_fifo_dir); - } + free_random_fifo (); crypto_free (); exit (EXIT_SUCCESS); } +#ifdef HAVE_UNIX_SOCKETS + /* Implementation of '-U -' */ static char * make_random_fifo (void) @@ -717,6 +740,29 @@ make_random_fifo (void) return unixsocket; } +static void +free_random_fifo (void) +{ + if (random_fifo) { + unlink (random_fifo); + free (random_fifo); + } + + if (random_fifo_dir) { + rmdir (random_fifo_dir); + free (random_fifo_dir); + } +} + +#else /* !HAVE_UNIX_SOCKETS */ + +static void +free_random_fifo (void) +{ +} + +#endif /* !HAVE_UNIX_SOCKETS */ + static struct backend * open_plugin_so (size_t i, const char *name, int short_name) { @@ -886,6 +932,8 @@ start_serving (void) free_listening_sockets (socks, nr_socks); } +#ifndef WIN32 + static void set_up_signals (void) { @@ -905,6 +953,23 @@ set_up_signals (void) sigaction (SIGPIPE, &sa, NULL); } +#else /* WIN32 */ + +static void +set_up_signals (void) +{ + + signal (SIGINT, handle_quit); + signal (SIGTERM, handle_quit); +} + +#endif /* WIN32 */ + +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + +static uid_t parseuser (const char *); +static gid_t parsegroup (const char *); + static void change_user (void) { @@ -937,6 +1002,77 @@ change_user (void) } } +static uid_t +parseuser (const char *id) +{ + struct passwd *pwd; + int saved_errno; + + errno = 0; + pwd = getpwnam (id); + + if (NULL == pwd) { + int val; + + saved_errno = errno; + + if (sscanf (id, "%d", &val) == 1) + return val; + + fprintf (stderr, "%s: -u option: %s is not a valid user name or uid", + program_name, id); + if (saved_errno != 0) + fprintf (stderr, " (getpwnam error: %s)", strerror (saved_errno)); + fprintf (stderr, "\n"); + exit (EXIT_FAILURE); + } + + return pwd->pw_uid; +} + +static gid_t +parsegroup (const char *id) +{ + struct group *grp; + int saved_errno; + + errno = 0; + grp = getgrnam (id); + + if (NULL == grp) { + int val; + + saved_errno = errno; + + if (sscanf (id, "%d", &val) == 1) + return val; + + fprintf (stderr, "%s: -g option: %s is not a valid group name or gid", + program_name, id); + if (saved_errno != 0) + fprintf (stderr, " (getgrnam error: %s)", strerror (saved_errno)); + fprintf (stderr, "\n"); + exit (EXIT_FAILURE); + } + + return grp->gr_gid; +} + +#else /* a platform like Windows which lacks pwd/grp functions */ + +static void +change_user (void) +{ + if (user || group) { + fprintf (stderr, "%s: " + "-u and -g options are not available on this plaform\n", + program_name); + exit (EXIT_FAILURE); + } +} + +#endif + static void write_pidfile (void) { @@ -967,6 +1103,8 @@ write_pidfile (void) debug ("written pidfile %s", pidfile); } +#ifndef WIN32 + static void fork_into_background (void) { @@ -1003,6 +1141,24 @@ fork_into_background (void) debug ("forked into background (new pid = %d)", getpid ()); } +#else /* WIN32 */ + +static void +fork_into_background (void) +{ + if (foreground) + return; + + fprintf (stderr, "%s: cannot fork into background on Windows.\n" + "You must use -f or equivalent option.\n", + program_name); + exit (EXIT_FAILURE); +} + +#endif /* WIN32 */ + +#ifndef WIN32 + static void run_command (void) { @@ -1086,61 +1242,22 @@ run_command (void) debug ("forked into background (new pid = %d)", getpid ()); } -static uid_t -parseuser (const char *id) -{ - struct passwd *pwd; - int saved_errno; - - errno = 0; - pwd = getpwnam (id); - - if (NULL == pwd) { - int val; - - saved_errno = errno; +#else /* !WIN32 */ - if (sscanf (id, "%d", &val) == 1) - return val; - - fprintf (stderr, "%s: -u option: %s is not a valid user name or uid", - program_name, id); - if (saved_errno != 0) - fprintf (stderr, " (getpwnam error: %s)", strerror (saved_errno)); - fprintf (stderr, "\n"); - exit (EXIT_FAILURE); - } - - return pwd->pw_uid; -} - -static gid_t -parsegroup (const char *id) +static void +run_command (void) { - struct group *grp; - int saved_errno; - - errno = 0; - grp = getgrnam (id); - - if (NULL == grp) { - int val; + if (!run) + return; - saved_errno = errno; - - if (sscanf (id, "%d", &val) == 1) - return val; + fprintf ("%s: cannot use --run on Windows.\n", + program_name); + exit (EXIT_FAILURE); +} - fprintf (stderr, "%s: -g option: %s is not a valid group name or gid", - program_name, id); - if (saved_errno != 0) - fprintf (stderr, " (getgrnam error: %s)", strerror (saved_errno)); - fprintf (stderr, "\n"); - exit (EXIT_FAILURE); - } +#endif /* WIN32 */ - return grp->gr_gid; -} +#ifndef WIN32 /* Returns 0 if no socket activation, or the number of FDs. * See also virGetListenFDs in libvirt.org:src/util/virutil.c @@ -1199,6 +1316,16 @@ get_socket_activation (void) return nr_fds; } +#else /* WIN32 */ + +static unsigned int +get_socket_activation (void) +{ + return 0; +} + +#endif /* WIN32 */ + /* When parsing plugin and filter config key=value from the command * line, check that the key is a simple alphanumeric with period, * underscore or dash. diff --git a/server/quit.c b/server/quit.c index c6f829e..edfc3ea 100644 --- a/server/quit.c +++ b/server/quit.c @@ -47,8 +47,16 @@ * a race. */ volatile int quit; + +#ifndef WIN32 int quit_fd; static int write_quit_fd; +#else +HANDLE quit_fd; +static HANDLE write_quit_fd; +#endif + +#ifndef WIN32 void set_up_quit_pipe (void) @@ -63,12 +71,47 @@ set_up_quit_pipe (void) write_quit_fd = fds[1]; } +#else /* WIN32 */ + +/* Non-blocking I/O is not possible on anonymous pipes in Windows, so + * we have to create a random named pipe. See: + * https://stackoverflow.com/questions/60645/overlapped-i-o-on-anonymous-pipe + */ +void +set_up_quit_pipe (void) +{ + char name[64]; + + snprintf (name, sizeof name, "\\\\.\\Pipe\\nbdkit.%lu", + GetCurrentProcessId ()); + quit_fd = CreateNamedPipeA (name, PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE|PIPE_WAIT, + 1, 4096, 4096, 0, NULL); + if (quit_fd == INVALID_HANDLE_VALUE) { + fprintf (stderr, "%s: CreateNamedPipeA for read: %s: error %lu\n", + program_name, name, GetLastError ()); + exit (EXIT_FAILURE); + } + + write_quit_fd = CreateFileA (name, GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (write_quit_fd == INVALID_HANDLE_VALUE) { + fprintf (stderr, "%s: CreateNamedPipeA for write: %s: error %lu\n", + program_name, name, GetLastError ()); + exit (EXIT_FAILURE); + } +} + +#endif /* WIN32 */ + void handle_quit (int sig) { set_quit (); } +#ifndef WIN32 + void set_quit (void) { @@ -80,3 +123,16 @@ set_quit (void) write (write_quit_fd, &c, 1); #pragma GCC diagnostic pop } + +#else /* WIN32 */ + +void +set_quit (void) +{ + char c = 0; + + quit = 1; + WriteFile (write_quit_fd, &c, 1, NULL, NULL); +} + +#endif /* WIN32 */ diff --git a/server/sockets.c b/server/sockets.c index cc15c5e..eb19a15 100644 --- a/server/sockets.c +++ b/server/sockets.c @@ -39,12 +39,32 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> +#include <errno.h> +#include <assert.h> + +#ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> +#endif + +#ifdef HAVE_SYS_UN_H #include <sys/un.h> +#endif + +#ifdef HAVE_NETDB_H #include <netdb.h> +#endif + +#ifdef HAVE_POLL_H #include <poll.h> -#include <errno.h> -#include <assert.h> +#endif + +#ifdef HAVE_WS2TCPIP_H +#include <ws2tcpip.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif #ifdef HAVE_SELINUX_SELINUX_H #include <selinux/selinux.h> @@ -86,6 +106,8 @@ clear_selinux_label (void) #endif } +#ifdef HAVE_UNIX_SOCKETS + int * bind_unix_socket (size_t *nr_socks) { @@ -140,6 +162,23 @@ bind_unix_socket (size_t *nr_socks) return ret; } +#else /* !HAVE_UNIX_SOCKETS */ + +int * +bind_unix_socket (size_t *nr_socks) +{ + fprintf (stderr, "%s: -U option: Unix domain sockets " + "are not supported on this platform\n", + program_name); + exit (EXIT_FAILURE); +} + +#endif /* !HAVE_UNIX_SOCKETS */ + +#ifndef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#endif + int * bind_tcpip_socket (size_t *nr_socks) { @@ -314,6 +353,8 @@ accept_connection (int listen_sock) */ } +#ifndef WIN32 + /* Check the list of sockets plus quit_fd until a POLLIN event occurs * on any of them. * @@ -360,6 +401,41 @@ check_sockets_and_quit_fd (int *socks, size_t nr_socks) } } +#else /* WIN32 */ + +static void +check_sockets_and_quit_fd (int *socks, size_t nr_socks) +{ + size_t i; + HANDLE handles[nr_socks+1]; + DWORD r; + + for (i = 0; i < nr_socks; ++i) + handles[i] = socks[i]; + handles[nr_socks] = quit_fd; + + r = WaitForMultipleObjectsEx ((DWORD) (nr_socks+1), handles, + FALSE, INFINITE, TRUE); + if (r == WAIT_FAILED) { + fprintf (stderr, "%s: WaitForMultipleObjectsEx: error %lu\n", + program_name, GetLastError ()); + exit (EXIT_FAILURE); + } + + if (r == WAIT_OBJECT_0 + nr_socks) /* quit_fd signalled. */ + return; + + if (r >= WAIT_OBJECT_0 && r <= WAIT_OBJECT_0 + nr_socks - 1) { + i = r - WAIT_OBJECT_0; + accept_connection (socks[i]); + return; + } + + debug ("WaitForMultipleObjectsEx: unexpected return value: %lu\n", r); +} + +#endif /* WIN32 */ + void accept_incoming_connections (int *socks, size_t nr_socks) { diff --git a/server/utils.c b/server/utils.c index d67ec43..ad2726c 100644 --- a/server/utils.c +++ b/server/utils.c @@ -41,9 +41,12 @@ #include <string.h> #include <unistd.h> #include <limits.h> -#include <termios.h> #include <errno.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif + #include "internal.h" #include "realpath.h" #include "getline.h" @@ -184,12 +187,72 @@ nbdkit_parse_bool (const char *str) return -1; } +#ifndef WIN32 + +typedef struct termios echo_mode; + +static void +echo_off (echo_mode *old_mode) +{ + struct termios temp; + int tty; + + tty = isatty (0); + if (tty) { + tcgetattr (0, old_mode); + temp = *old_mode; + temp.c_lflag &= ~ECHO; + tcsetattr (0, TCSAFLUSH, &temp); + } +} + +static void +echo_restore (const echo_mode *old_mode) +{ + int tty; + + tty = isatty (0); + if (tty) + tcsetattr (0, TCSAFLUSH, old_mode); +} + +#else /* WIN32 */ + +/* Windows implementation of tty echo off based on this: + * https://stackoverflow.com/a/1455007 + */ +typedef DWORD echo_mode; + +static void +echo_off (echo_mode *old_mode) +{ + HANDLE h_stdin; + DWORD mode; + + h_stdin = GetStdHandle (STD_INPUT_HANDLE); + GetConsoleMode (h_stdin, old_mode); + mode = *old_mode; + mode &= ~ENABLE_ECHO_INPUT; + SetConsoleMode (h_stdin, mode); +} + +static void +echo_restore (const echo_mode *old_mode) +{ + HANDLE h_stdin; + + h_stdin = GetStdHandle (STD_INPUT_HANDLE); + SetConsoleMode (h_stdin, *old_mode); +} + +#endif /* WIN32 */ + /* Read a password from configuration value. */ int nbdkit_read_password (const char *value, char **password) { - int tty, err;; - struct termios orig, temp; + int err; + echo_mode orig; ssize_t r; size_t n; FILE *fp; @@ -199,20 +262,13 @@ nbdkit_read_password (const char *value, char **password) printf ("password: "); /* Set no echo. */ - tty = isatty (0); - if (tty) { - tcgetattr (0, &orig); - temp = orig; - temp.c_lflag &= ~ECHO; - tcsetattr (0, TCSAFLUSH, &temp); - } + echo_off (&orig); r = getline (password, &n, stdin); err = errno; /* Restore echo. */ - if (tty) - tcsetattr (0, TCSAFLUSH, &orig); + echo_restore (&orig); /* Complete the printf above. */ printf ("\n"); diff --git a/.gitignore b/.gitignore index 35561e9..ba29b70 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.trs .deps +.dirstamp .gdb_history .libs Makefile @@ -55,10 +56,13 @@ Makefile.in /ltmain.sh /missing /nbdkit +/nbdkit.exe /plugins/example4/nbdkit-example4-plugin /plugins/tar/nbdkit-tar-plugin /podwrapper.pl +/server/libnbdkit.a /server/nbdkit +/server/nbdkit.exe /server/nbdkit.pc /server/protostrings.c /server/synopsis.c diff --git a/TODO b/TODO index 2ef8e1a..5a4e598 100644 --- a/TODO +++ b/TODO @@ -131,3 +131,24 @@ nbdkit processes. The nbd plugin (plugins/nbd) already contains an NBD client, so we could factor this client out and make it available to other plugins to use. + +Windows support +--------------- + +The following features are not yet implemented on Windows: + +Because there is no fork(2) we cannot fork into background (ie. -f or +equivalent must always be used). --run does not work for a similar +reason. + +-u/-g flags do not work. + +No socket activation. Unclear if this makes sense on Windows, since +there may not be a way to pass opened file descriptors to a newly +created process. + +Unix domain sockets (ie. -U option) do not work, the clue being in the +name. However is there an equivalent filesystem sockets feature in +Windows that we should be using instead? + +Many plugins and filters have not yet been ported to Windows. diff --git a/server/Makefile.am b/server/Makefile.am index 80efef5..c6c6e15 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -32,7 +32,9 @@ include $(top_srcdir)/common-rules.mk -EXTRA_DIST = nbdkit.syms +EXTRA_DIST = \ + nbdkit.def \ + nbdkit.syms sbin_PROGRAMS = nbdkit @@ -86,6 +88,19 @@ if USE_LINKER_SCRIPT_FOR_SERVER nbdkit_LDFLAGS += -Wl,--version-script=$(srcdir)/nbdkit.syms endif +if IS_WINDOWS + +# On Windows, generate an import library so that plugins can link +# against the executable. +# https://stackoverflow.com/questions/15454968/dll-plugin-that-uses-functions-defined-in-the-main-executable + +lib_LIBRARIES = libnbdkit.a + +libnbdkit.a: .libs/nbdkit.exe + $(DLLTOOL) -v .libs/nbdkit.exe -D nbdkit.exe -d nbdkit.def -l $@ + +endif + # protostrings.c is generated from the protocol.h header file where it # is used to map NBD protocol flags to strings. diff --git a/server/nbdkit.def b/server/nbdkit.def new file mode 100644 index 0000000..df6f9a6 --- /dev/null +++ b/server/nbdkit.def @@ -0,0 +1,47 @@ +; nbdkit +; Copyright (C) 2018 Red Hat Inc. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are +; met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; * Neither the name of Red Hat nor the names of its contributors may be +; used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +; USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +; OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; Controls the visibility of symbols on Windows. +; +; NOTE: If you edit this file you must also edit nbdkit.syms. +; +EXPORTS + nbdkit_absolute_path + nbdkit_debug + nbdkit_error + nbdkit_parse_bool + nbdkit_parse_size + nbdkit_read_password + nbdkit_realpath + nbdkit_set_error + nbdkit_vdebug + nbdkit_verror diff --git a/server/nbdkit.syms b/server/nbdkit.syms index 672abd2..f889311 100644 --- a/server/nbdkit.syms +++ b/server/nbdkit.syms @@ -36,6 +36,8 @@ # functions from nbdkit, so this script lists only the symbols we want # to export. +# NOTE: If you edit this file you must also edit nbdkit.def. + { # The functions we want plugins and filters to call. global: diff --git a/tests/Makefile.am b/tests/Makefile.am index e96dac9..f13d091 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -183,7 +183,11 @@ test_ansi_c_plugin_la_CFLAGS = \ # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_ansi_c_plugin_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_ansi_c_plugin_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif if HAVE_CXX # This builds a plugin and a filter using the C++ compiler. They @@ -205,7 +209,11 @@ test_cxx_plugin_la_CXXFLAGS = \ # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_cxx_plugin_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_cxx_plugin_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif test_cxx_filter_la_SOURCES = \ test-cxx-filter.cpp \ @@ -217,7 +225,11 @@ test_cxx_filter_la_CXXFLAGS = \ # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_cxx_filter_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_cxx_filter_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif endif HAVE_CXX # Exit with parent test. @@ -533,7 +545,11 @@ libvixDiskLib_la_CXXFLAGS = \ # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html libvixDiskLib_la_LDFLAGS = \ - -shared -version-number 6:0:0 -rpath /nowhere + -shared -version-number 6:0:0 -rpath /nowhere -no-undefined +if IS_WINDOWS +libvixDiskLib_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif # zero plugin test. TESTS += test-zero.sh @@ -695,7 +711,11 @@ test_layers_plugin_la_CFLAGS = $(WARNINGS_CFLAGS) # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_layers_plugin_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_layers_plugin_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif test_layers_filter1_la_SOURCES = \ test-layers-filter.c \ @@ -705,7 +725,11 @@ test_layers_filter1_la_CFLAGS = $(WARNINGS_CFLAGS) -Dlayer='"filter1"' # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_layers_filter1_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_layers_filter1_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif test_layers_filter2_la_SOURCES = \ test-layers-filter.c \ @@ -715,7 +739,11 @@ test_layers_filter2_la_CFLAGS = $(WARNINGS_CFLAGS) -Dlayer='"filter2"' # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_layers_filter2_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_layers_filter2_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif test_layers_filter3_la_SOURCES = \ test-layers-filter.c \ @@ -725,7 +753,11 @@ test_layers_filter3_la_CFLAGS = $(WARNINGS_CFLAGS) -Dlayer='"filter3"' # For use of the -rpath option, see: # https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html test_layers_filter3_la_LDFLAGS = \ - -module -avoid-version -shared -rpath /nowhere + -module -avoid-version -shared -rpath /nowhere -no-undefined +if IS_WINDOWS +test_layers_filter3_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit +endif # blocksize filter test. TESTS += test-blocksize.sh -- 2.20.1
Richard W.M. Jones
2019-Jan-14 12:18 UTC
[Libguestfs] [PATCH nbdkit incomplete 5/5] plugins: Port some plugins to Windows.
Now ‘--disable-plugins’ can be removed from the previous commit to enable some plugins and run them under wine: sudo dnf install mingw64-gcc mingw64-dlfcn \ mingw64-gnutls mingw64-xz mingw64-zlib mingw64-configure make wine ./server/nbdkit.exe -fv \ ./plugins/memory/.libs/nbdkit-memory-plugin.dll size=1M --- plugins/data/data.c | 2 ++ plugins/data/Makefile.am | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/data/data.c b/plugins/data/data.c index f9d3881..4a94b29 100644 --- a/plugins/data/data.c +++ b/plugins/data/data.c @@ -49,6 +49,8 @@ #include "sparse.h" +#include "strndup.h" + /* If raw|base64|data parameter seen. */ static int data_seen = 0; diff --git a/plugins/data/Makefile.am b/plugins/data/Makefile.am index 4976d04..d7c22b8 100644 --- a/plugins/data/Makefile.am +++ b/plugins/data/Makefile.am @@ -43,6 +43,7 @@ nbdkit_data_plugin_la_SOURCES = \ $(top_srcdir)/include/nbdkit-plugin.h nbdkit_data_plugin_la_CPPFLAGS = \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/sparse @@ -50,11 +51,13 @@ nbdkit_data_plugin_la_CFLAGS = \ $(WARNINGS_CFLAGS) \ $(GNUTLS_CFLAGS) nbdkit_data_plugin_la_LDFLAGS = \ - -module -avoid-version -shared \ + -module -avoid-version -shared -no-undefined \ -Wl,--version-script=$(top_srcdir)/plugins/plugins.syms nbdkit_data_plugin_la_LIBADD = \ + -L$(top_builddir)/server -lnbdkit \ $(top_builddir)/common/sparse/libsparse.la \ - $(GNUTLS_LIBS) + $(GNUTLS_LIBS) \ + $(top_builddir)/lib/libcompat.la if HAVE_POD -- 2.20.1
Richard W.M. Jones
2019-Jan-15 11:59 UTC
Re: [Libguestfs] [PATCH nbdkit incomplete 0/5] Port to Windows.
I got bored with porting to Windows. However I did get further and the server does at least start up and accept connections now (although it doesn't complete the initial negotiation). I pushed my work so far to a private branch: https://github.com/rwmjones/nbdkit/commits/windows Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
Seemingly Similar Threads
- [PATCH nbdkit 0/9] Port to Windows.
- [PATCH nbdkit 0/13] Port to Windows without using a separate library.
- [PATCH EXPERIMENTAL nbdkit 0/2] Port to Windows using mingw.
- Re: [PATCH nbdkit 3/9] server: Add general replacements for missing functions using LIBOBJS.
- [nbdkit PATCH v2 0/8] Support parallel transactions within single connection