diff --git a/0001-TODO-Mark-some-items-done.patch b/0001-TODO-Mark-some-items-done.patch new file mode 100644 index 0000000..73c853b --- /dev/null +++ b/0001-TODO-Mark-some-items-done.patch @@ -0,0 +1,44 @@ +From ed86327eef65c2be126cc8b1d1390a627dc89024 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 30 Jul 2019 15:41:55 -0500 +Subject: [PATCH 01/11] TODO: Mark some items done + +0.1.9 included an example of glib (bc3b4230); on the other hand, we +may still want examples of use of ppoll (I experimented with that on +nbdkit but decided that pipe-to-self was more efficient), or pollfd +(Linux-only). + +0.1.9 added callback(FREE) (2d9b98e9) which let us fix language +bindings to release callbacks as soon as possible. + +0.9.6 got rid of cookies in the completion callback (7091933f), which +in turn avoids the potential race of an early callback. +--- + TODO | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/TODO b/TODO +index 6f3c7d8..87bcc1a 100644 +--- a/TODO ++++ b/TODO +@@ -1,16 +1,9 @@ +-Explore separation of nbd_aio_pread/nbd_aio_submit(callback) since +-current nbd_aio_pread_callback(callback) can race into the callback +-before cookie is known to the user. +- + Explore if nbd_aio_notify_error is needed for faster response if + server goes away. + +-Improve python bindings to free persistent closure wrappers at time +-of command completion rather than nbd close. +- + Bindings in other languages. + +-Example code integrating with glib2, APR pollset (and others?). ++Example code integrating with ppoll, pollfd, APR pollset (and others?). + + Example command line utils to copy in/out (like qemu-img convert). + +-- +2.22.0 + diff --git a/0002-tests-Make-sure-errors-test-uses-serialized-nbdkit.patch b/0002-tests-Make-sure-errors-test-uses-serialized-nbdkit.patch new file mode 100644 index 0000000..ba5414f --- /dev/null +++ b/0002-tests-Make-sure-errors-test-uses-serialized-nbdkit.patch @@ -0,0 +1,32 @@ +From 8eac86f4a53e6523c5c1693cca1f20f4d8034125 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Thu, 1 Aug 2019 05:51:54 -0500 +Subject: [PATCH 02/11] tests: Make sure errors test uses serialized nbdkit + +An upcoming nbdkit release will be relaxing sh scripts to be fully +parallel unless the script requests otherwise; but our errors test +depends on the current serialized execution. Thankfully, older nbdkit +does not care if we provide the new hook for the sake of newer nbdkit. + +An audit for other testsuite use of nbdkit sh turns up +eflags-plugin.sh and meta-base-allocation.sh, but those will continue +to work in a parallel model. +--- + tests/errors.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/errors.c b/tests/errors.c +index 4043c78..8a916fe 100644 +--- a/tests/errors.c ++++ b/tests/errors.c +@@ -104,6 +104,7 @@ main (int argc, char *argv[]) + + if (dprintf (script_fd, "case $1 in\n" + " get_size) echo 128m || exit 1 ;;\n" ++ " thread_model) echo serialize_all_requests; exit 0 ;;\n" + " pread) printf 'ENOMEM ' >&2; exit 1 ;;\n" + " can_write) exit 0 ;;\n" + " pwrite)\n" +-- +2.22.0 + diff --git a/0003-tests-Add-some-basic-compile-tests-inspired-by-nbdki.patch b/0003-tests-Add-some-basic-compile-tests-inspired-by-nbdki.patch new file mode 100644 index 0000000..9cd999f --- /dev/null +++ b/0003-tests-Add-some-basic-compile-tests-inspired-by-nbdki.patch @@ -0,0 +1,650 @@ +From 80b922b6b6eaa504f98184ac816cc0ede15365bc Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 10:30:39 +0100 +Subject: [PATCH 03/11] tests: Add some basic compile tests, inspired by + nbdkit. + +* Compile a program which only includes + +* Compile a program which only opens and closes the handle. + +* Compile a program using ANSI C settings. + +* Test the debug flag can be set and cleared, and the effect of the + LIBNBD_DEBUG environment variable. + +* Test that the export name can be set and read. + +* Test the package name and version APIs. +--- + .gitignore | 7 ++ + tests/Makefile.am | 135 +++++++++++++++++++++++++++--------- + tests/compile-ansi-c.c | 43 ++++++++++++ + tests/compile-header-only.c | 27 ++++++++ + tests/compile.c | 41 +++++++++++ + tests/debug-environment.c | 68 ++++++++++++++++++ + tests/debug.c | 70 +++++++++++++++++++ + tests/export-name.c | 67 ++++++++++++++++++ + tests/version.c | 58 ++++++++++++++++ + 9 files changed, 482 insertions(+), 34 deletions(-) + create mode 100644 tests/compile-ansi-c.c + create mode 100644 tests/compile-header-only.c + create mode 100644 tests/compile.c + create mode 100644 tests/debug-environment.c + create mode 100644 tests/debug.c + create mode 100644 tests/export-name.c + create mode 100644 tests/version.c + +diff --git a/.gitignore b/.gitignore +index ed1e03e..e69d243 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -109,13 +109,19 @@ Makefile.in + /tests/can-not-trim-flag + /tests/can-zero-flag + /tests/closure-lifetimes ++/tests/compile ++/tests/compile-ansi-c ++/tests/compile-header-only + /tests/connect-tcp + /tests/connect-tls-certs + /tests/connect-tls-psk + /tests/connect-unix + /tests/connect-uri-tcp + /tests/connect-uri-unix ++/tests/debug ++/tests/debug-environment + /tests/errors ++/tests/export-name + /tests/functions.sh + /tests/get-size + /tests/is-rotational-flag +@@ -123,6 +129,7 @@ Makefile.in + /tests/keys.psk + /tests/meta-base-allocation + /tests/oldstyle ++/tests/version + /tests/pki/ + /tests/read-only-flag + /tests/read-write-flag +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 3b8448e..59318b4 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -39,40 +39,9 @@ EXTRA_DIST = \ + synch-parallel-tls.sh \ + $(NULL) + +-if HAVE_NBDKIT +- + check_DATA = +- +-check_PROGRAMS = \ +- errors \ +- server-death \ +- get-size \ +- read-only-flag \ +- read-write-flag \ +- can-flush-flag \ +- can-not-flush-flag \ +- can-fua-flag \ +- can-not-fua-flag \ +- is-rotational-flag \ +- is-not-rotational-flag \ +- can-trim-flag \ +- can-not-trim-flag \ +- can-zero-flag \ +- can-multi-conn-flag \ +- can-not-multi-conn-flag \ +- oldstyle \ +- connect-unix \ +- connect-tcp \ +- connect-uri-unix \ +- connect-uri-tcp \ +- aio-parallel \ +- aio-parallel-load \ +- synch-parallel \ +- meta-base-allocation \ +- closure-lifetimes \ +- $(NULL) +-# can-cache-flag +-# can-not-cache-flag ++check_PROGRAMS = ++TESTS = + + # Make sure that $srcdir is available to tests. + # Enable debug in all tests. +@@ -80,7 +49,103 @@ TESTS_ENVIRONMENT = srcdir=$(srcdir) LIBNBD_DEBUG=1 + # Use the ./run script so we're always using the local library and tools. + LOG_COMPILER = $(top_builddir)/run + +-TESTS = \ ++#---------------------------------------------------------------------- ++# The following tests do not need an NBD server. ++ ++check_PROGRAMS += \ ++ compile-header-only \ ++ compile \ ++ compile-ansi-c \ ++ debug \ ++ debug-environment \ ++ version \ ++ export-name \ ++ $(NULL) ++ ++TESTS += \ ++ compile-header-only \ ++ compile \ ++ compile-ansi-c \ ++ debug \ ++ debug-environment \ ++ version \ ++ export-name \ ++ $(NULL) ++ ++compile_header_only_SOURCES = compile-header-only.c ++compile_header_only_CPPFLAGS = -I$(top_srcdir)/include ++compile_header_only_CFLAGS = $(WARNINGS_CFLAGS) ++compile_header_only_LDADD = $(top_builddir)/lib/libnbd.la ++ ++compile_SOURCES = compile.c ++compile_CPPFLAGS = -I$(top_srcdir)/include ++compile_CFLAGS = $(WARNINGS_CFLAGS) ++compile_LDADD = $(top_builddir)/lib/libnbd.la ++ ++compile_ansi_c_SOURCES = compile-ansi-c.c ++compile_ansi_c_CPPFLAGS = \ ++ -I$(top_srcdir)/include \ ++ -std=c90 -pedantic ++compile_ansi_c_CFLAGS = $(WARNINGS_CFLAGS) ++compile_ansi_c_LDADD = $(top_builddir)/lib/libnbd.la ++ ++debug_SOURCES = debug.c ++debug_CPPFLAGS = -I$(top_srcdir)/include ++debug_CFLAGS = $(WARNINGS_CFLAGS) ++debug_LDADD = $(top_builddir)/lib/libnbd.la ++ ++debug_environment_SOURCES = debug-environment.c ++debug_environment_CPPFLAGS = -I$(top_srcdir)/include ++debug_environment_CFLAGS = $(WARNINGS_CFLAGS) ++debug_environment_LDADD = $(top_builddir)/lib/libnbd.la ++ ++version_SOURCES = version.c ++version_CPPFLAGS = -I$(top_srcdir)/include ++version_CFLAGS = $(WARNINGS_CFLAGS) ++version_LDADD = $(top_builddir)/lib/libnbd.la ++ ++export_name_SOURCES = export-name.c ++export_name_CPPFLAGS = -I$(top_srcdir)/include ++export_name_CFLAGS = $(WARNINGS_CFLAGS) ++export_name_LDADD = $(top_builddir)/lib/libnbd.la ++ ++#---------------------------------------------------------------------- ++# The following tests require nbdkit as an NBD server to test against. ++ ++if HAVE_NBDKIT ++ ++check_PROGRAMS += \ ++ errors \ ++ server-death \ ++ get-size \ ++ read-only-flag \ ++ read-write-flag \ ++ can-flush-flag \ ++ can-not-flush-flag \ ++ can-fua-flag \ ++ can-not-fua-flag \ ++ is-rotational-flag \ ++ is-not-rotational-flag \ ++ can-trim-flag \ ++ can-not-trim-flag \ ++ can-zero-flag \ ++ can-multi-conn-flag \ ++ can-not-multi-conn-flag \ ++ oldstyle \ ++ connect-unix \ ++ connect-tcp \ ++ connect-uri-unix \ ++ connect-uri-tcp \ ++ aio-parallel \ ++ aio-parallel-load \ ++ synch-parallel \ ++ meta-base-allocation \ ++ closure-lifetimes \ ++ $(NULL) ++# can-cache-flag ++# can-not-cache-flag ++ ++TESTS += \ + errors \ + server-death \ + get-size \ +@@ -286,7 +351,9 @@ closure_lifetimes_CPPFLAGS = -I$(top_srcdir)/include + closure_lifetimes_CFLAGS = $(WARNINGS_CFLAGS) + closure_lifetimes_LDADD = $(top_builddir)/lib/libnbd.la + ++#---------------------------------------------------------------------- + # Testing TLS support. ++ + if HAVE_GNUTLS + + if HAVE_CERTTOOL +diff --git a/tests/compile-ansi-c.c b/tests/compile-ansi-c.c +new file mode 100644 +index 0000000..0d48618 +--- /dev/null ++++ b/tests/compile-ansi-c.c +@@ -0,0 +1,43 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Test that (only simple) programs can be compiled by an ANSI C ++ * compiler. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct nbd_handle *nbd; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/compile-header-only.c b/tests/compile-header-only.c +new file mode 100644 +index 0000000..52b93d7 +--- /dev/null ++++ b/tests/compile-header-only.c +@@ -0,0 +1,27 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Check that does not require any other headers. */ ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ return 0; ++} +diff --git a/tests/compile.c b/tests/compile.c +new file mode 100644 +index 0000000..d7ef98c +--- /dev/null ++++ b/tests/compile.c +@@ -0,0 +1,41 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Compile, open and close a handle. */ ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct nbd_handle *nbd; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/debug-environment.c b/tests/debug-environment.c +new file mode 100644 +index 0000000..e11708a +--- /dev/null ++++ b/tests/debug-environment.c +@@ -0,0 +1,68 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Check that LIBNBD_DEBUG=0|1 affects the debug flag. */ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++static int ++get_debug_flag (void) ++{ ++ struct nbd_handle *nbd; ++ int r; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = nbd_get_debug (nbd); ++ if (r == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ nbd_close (nbd); ++ ++ return r; ++} ++ ++int ++main (int argc, char *argv[]) ++{ ++ setenv ("LIBNBD_DEBUG", "1", 1); ++ assert (get_debug_flag () == 1); ++ ++ setenv ("LIBNBD_DEBUG", "0", 1); ++ assert (get_debug_flag () == 0); ++ ++ setenv ("LIBNBD_DEBUG", "", 1); ++ assert (get_debug_flag () == 0); ++ ++ unsetenv ("LIBNBD_DEBUG"); ++ assert (get_debug_flag () == 0); ++ ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/debug.c b/tests/debug.c +new file mode 100644 +index 0000000..af2e80f +--- /dev/null ++++ b/tests/debug.c +@@ -0,0 +1,70 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Test setting and reading the debug flag. */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct nbd_handle *nbd; ++ int r; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = nbd_set_debug (nbd, true); ++ if (r == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = nbd_get_debug (nbd); ++ if (r == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ assert (r == 1); ++ ++ r = nbd_set_debug (nbd, false); ++ if (r == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = nbd_get_debug (nbd); ++ if (r == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ assert (r == 0); ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/export-name.c b/tests/export-name.c +new file mode 100644 +index 0000000..7cbc3cd +--- /dev/null ++++ b/tests/export-name.c +@@ -0,0 +1,67 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Test setting and reading the export name. */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++static void ++check_export_name (struct nbd_handle *nbd, const char *str) ++{ ++ char *r; ++ ++ if (nbd_set_export_name (nbd, str) == -1) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = nbd_get_export_name (nbd); ++ if (r == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ assert (strcmp (str, r) == 0); ++ free (r); ++} ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct nbd_handle *nbd; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ check_export_name (nbd, "/"); ++ check_export_name (nbd, "123"); ++ check_export_name (nbd, ""); ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/version.c b/tests/version.c +new file mode 100644 +index 0000000..1ba3f58 +--- /dev/null ++++ b/tests/version.c +@@ -0,0 +1,58 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Read the package and version from the handle. */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct nbd_handle *nbd; ++ const char *s; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ ++ s = nbd_get_package_name (nbd); ++ if (s == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ assert (strcmp (s, PACKAGE_NAME) == 0); ++ ++ s = nbd_get_version (nbd); ++ if (s == NULL) { ++ fprintf (stderr, "%s\n", nbd_get_error ()); ++ exit (EXIT_FAILURE); ++ } ++ assert (strcmp (s, PACKAGE_VERSION) == 0); ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +-- +2.22.0 + diff --git a/0004-Fix-compilation-with-C.patch b/0004-Fix-compilation-with-C.patch new file mode 100644 index 0000000..f3829b7 --- /dev/null +++ b/0004-Fix-compilation-with-C.patch @@ -0,0 +1,162 @@ +From e1efb1fd2efbadfa0a2b53662f2757c728e119ab Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 11:00:40 +0100 +Subject: [PATCH 04/11] Fix compilation with C++. + +We lacked the appropriate extern "C" section in the header, so +compilation would fail if you were using C++. + +This also adds a simple regression test. +--- + .gitignore | 1 + + configure.ac | 11 +++++++++ + generator/generator | 8 +++++++ + tests/Makefile.am | 12 ++++++++++ + tests/compile-cxx.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 84 insertions(+) + create mode 100644 tests/compile-cxx.cpp + +diff --git a/.gitignore b/.gitignore +index e69d243..9558577 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -111,6 +111,7 @@ Makefile.in + /tests/closure-lifetimes + /tests/compile + /tests/compile-ansi-c ++/tests/compile-cxx + /tests/compile-header-only + /tests/connect-tcp + /tests/connect-tls-certs +diff --git a/configure.ac b/configure.ac +index 30d7f90..8c47e61 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -44,6 +44,17 @@ AM_PROG_CC_C_O + + AX_PTHREAD + ++dnl Check for C++ (optional, we just use this to test the header ++dnl can be included from C++ code). ++AC_PROG_CXX ++ ++dnl The C++ compiler test is pretty useless because even if it fails ++dnl it sets CXX=g++. So test the compiler actually works. ++AC_MSG_CHECKING([if the C++ compiler really really works]) ++AS_IF([$CXX --version >&AS_MESSAGE_LOG_FD 2>&1],[have_cxx=yes],[have_cxx=no]) ++AC_MSG_RESULT([$have_cxx]) ++AM_CONDITIONAL([HAVE_CXX], [test "$have_cxx" = "yes"]) ++ + AC_ARG_ENABLE([gcc-warnings], + [AS_HELP_STRING([--enable-gcc-warnings], + [turn on lots of GCC warnings (for developers)])], +diff --git a/generator/generator b/generator/generator +index 62ca99c..0d10214 100755 +--- a/generator/generator ++++ b/generator/generator +@@ -3332,6 +3332,10 @@ let generate_include_libnbd_h () = + pr "#include \n"; + pr "#include \n"; + pr "\n"; ++ pr "#ifdef __cplusplus\n"; ++ pr "extern \"C\" {\n"; ++ pr "#endif\n"; ++ pr "\n"; + pr "struct nbd_handle;\n"; + pr "\n"; + pr "typedef void (*nbd_close_callback) (void *user_data);\n"; +@@ -3361,6 +3365,10 @@ let generate_include_libnbd_h () = + fun (ns, ctxts) -> print_ns ns ctxts + ) metadata_namespaces; + pr "\n"; ++ pr "#ifdef __cplusplus\n"; ++ pr "}\n"; ++ pr "#endif\n"; ++ pr "\n"; + pr "#endif /* LIBNBD_H */\n" + + let generate_lib_unlocked_h () = +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 59318b4..3064301 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -109,6 +109,18 @@ export_name_CPPFLAGS = -I$(top_srcdir)/include + export_name_CFLAGS = $(WARNINGS_CFLAGS) + export_name_LDADD = $(top_builddir)/lib/libnbd.la + ++if HAVE_CXX ++ ++check_PROGRAMS += compile-cxx ++TESTS += compile-cxx ++ ++compile_cxx_SOURCES = compile-cxx.cpp ++compile_cxx_CPPFLAGS = -I$(top_srcdir)/include ++compile_cxx_CXXFLAGS = $(WARNINGS_CFLAGS) ++compile_cxx_LDADD = $(top_builddir)/lib/libnbd.la ++ ++endif HAVE_CXX ++ + #---------------------------------------------------------------------- + # The following tests require nbdkit as an NBD server to test against. + +diff --git a/tests/compile-cxx.cpp b/tests/compile-cxx.cpp +new file mode 100644 +index 0000000..4c8447c +--- /dev/null ++++ b/tests/compile-cxx.cpp +@@ -0,0 +1,52 @@ ++/* NBD client library in userspace ++ * Copyright (C) 2013-2019 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 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* Test compilation with C++. */ ++ ++#ifndef __cplusplus ++#error "this test should be compiled with a C++ compiler" ++#endif ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++using namespace std; ++ ++int ++main () ++{ ++ struct nbd_handle *nbd; ++ ++ nbd = nbd_create (); ++ if (nbd == NULL) { ++ cerr << nbd_get_error () << endl; ++ exit (EXIT_FAILURE); ++ } ++ ++ cout << nbd_get_package_name (nbd) ++ << " " ++ << nbd_get_version (nbd) ++ << endl; ++ ++ nbd_close (nbd); ++ exit (EXIT_SUCCESS); ++} +-- +2.22.0 + diff --git a/0005-run-Set-MALLOC_CHECK_-1-when-using-.-run-or-running-.patch b/0005-run-Set-MALLOC_CHECK_-1-when-using-.-run-or-running-.patch new file mode 100644 index 0000000..49f8a34 --- /dev/null +++ b/0005-run-Set-MALLOC_CHECK_-1-when-using-.-run-or-running-.patch @@ -0,0 +1,25 @@ +From a892453f1c04ea33cf8b98dff5a7e1c21e7bf0ce Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 11:18:00 +0100 +Subject: [PATCH 05/11] run: Set MALLOC_CHECK_=1 when using ./run or running + the tests. + +--- + run.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/run.in b/run.in +index 56ed703..83c92a7 100755 +--- a/run.in ++++ b/run.in +@@ -73,6 +73,7 @@ export CAML_LD_LIBRARY_PATH + + # This is a cheap way to find some use-after-free and uninitialized + # read problems when using glibc. ++export MALLOC_CHECK_=1 + random_val="$(@AWK@ 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)" + export MALLOC_PERTURB_=$random_val + +-- +2.22.0 + diff --git a/0006-include-Remove-unused-definition-of-nbd_close_callba.patch b/0006-include-Remove-unused-definition-of-nbd_close_callba.patch new file mode 100644 index 0000000..469aa6a --- /dev/null +++ b/0006-include-Remove-unused-definition-of-nbd_close_callba.patch @@ -0,0 +1,29 @@ +From 9be99ad2ba0e81dc44f74b4dfc756b37a02de0fb Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 12:40:01 +0100 +Subject: [PATCH 06/11] include: Remove unused definition of + nbd_close_callback. + +This feature was removed in +commit 7f191b150b52ed50098976309a6af883d245fc56 but the typedef was +left in the header file accidentally. +--- + generator/generator | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/generator/generator b/generator/generator +index 0d10214..2a952cc 100755 +--- a/generator/generator ++++ b/generator/generator +@@ -3338,8 +3338,6 @@ let generate_include_libnbd_h () = + pr "\n"; + pr "struct nbd_handle;\n"; + pr "\n"; +- pr "typedef void (*nbd_close_callback) (void *user_data);\n"; +- pr "\n"; + List.iter (fun (n, i) -> pr "#define LIBNBD_%-30s %d\n" n i) constants; + pr "\n"; + pr "#define LIBNBD_CALLBACK_VALID 1\n"; +-- +2.22.0 + diff --git a/0007-generator-Generate-typedefs-automatically-for-Closur.patch b/0007-generator-Generate-typedefs-automatically-for-Closur.patch new file mode 100644 index 0000000..d2d60cb --- /dev/null +++ b/0007-generator-Generate-typedefs-automatically-for-Closur.patch @@ -0,0 +1,724 @@ +From 3b35624499d01a4a37df26db5333a5218b7960f8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 13:10:30 +0100 +Subject: [PATCH 07/11] generator: Generate typedefs automatically for Closure + arguments. + +For example nbd_set_debug takes a callback function. Previously this +was defined explicitly inside the function parameters. This commit +defines a new public typedef: + + typedef int (*nbd_debug_callback) (unsigned valid_flag, void *user_data, + const char *context, const char *msg); + +and then uses the typedef like this: + + extern int nbd_set_debug_callback (struct nbd_handle *h, + nbd_debug_callback debug_callback, + void *debug_callback_user_data); + +(Previously typedefs were available, but they were written by hand and +only used internally to the library.) + +This change necessitates that we uniquely name all of our closures +across methods (the same-named closure is required to have the same +cbargs). + +I took this opportunity to rename some, so especially completion +callbacks now have the type nbd_completion_callback. The generator +also checks they are named uniquely. + +This does not change the C API or ABI. +--- + generator/generator | 93 +++++++++++++++++++++++------ + generator/states-reply-simple.c | 12 ++-- + generator/states-reply-structured.c | 40 ++++++------- + generator/states-reply.c | 8 +-- + generator/states.c | 8 +-- + lib/aio.c | 12 ++-- + lib/debug.c | 12 ++-- + lib/handle.c | 6 +- + lib/internal.h | 20 ++----- + lib/rw.c | 61 +++++++++++-------- + 10 files changed, 165 insertions(+), 107 deletions(-) + +diff --git a/generator/generator b/generator/generator +index 2a952cc..6f89792 100755 +--- a/generator/generator ++++ b/generator/generator +@@ -924,7 +924,7 @@ Return the state of the debug flag on this handle."; + + "set_debug_callback", { + default_call with +- args = [ Closure { cbname="debug_fn"; ++ args = [ Closure { cbname="debug"; + cbargs=[String "context"; String "msg"] } ]; + ret = RErr; + shortdesc = "set the debug callback"; +@@ -1731,7 +1731,7 @@ C."; + "aio_pread_callback", { + default_call with + args = [ BytesPersistOut ("buf", "count"); UInt64 "offset"; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1778,7 +1778,7 @@ documented in C."; + UInt64 "offset"; + UInt "status"; + Mutable (Int "error")] }; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1814,7 +1814,7 @@ C."; + "aio_pwrite_callback", { + default_call with + args = [ BytesPersistIn ("buf", "count"); UInt64 "offset"; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1870,7 +1870,7 @@ Parameters behave as documented in C."; + + "aio_flush_callback", { + default_call with +- args = [ Closure { cbname="callback"; ++ args = [ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1904,7 +1904,7 @@ Parameters behave as documented in C."; + "aio_trim_callback", { + default_call with + args = [ UInt64 "count"; UInt64 "offset"; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1938,7 +1938,7 @@ Parameters behave as documented in C."; + "aio_cache_callback", { + default_call with + args = [ UInt64 "count"; UInt64 "offset"; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -1972,7 +1972,7 @@ Parameters behave as documented in C."; + "aio_zero_callback", { + default_call with + args = [ UInt64 "count"; UInt64 "offset"; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -2017,7 +2017,7 @@ Parameters behave as documented in C."; + ArrayAndLen (UInt32 "entries", + "nr_entries"); + Mutable (Int "error")] }; +- Closure { cbname="callback"; ++ Closure { cbname="completion"; + cbargs=[Mutable (Int "error")] }; + Flags "flags" ]; + ret = RInt64; +@@ -2363,6 +2363,25 @@ let rec group_by = function + | (day, x) :: rest -> + (day, [x]) :: group_by rest + ++let uniq ?(cmp = Pervasives.compare) xs = ++ let rec loop acc = function ++ | [] -> acc ++ | [x] -> x :: acc ++ | x :: (y :: _ as xs) when cmp x y = 0 -> ++ loop acc xs ++ | x :: (y :: _ as xs) -> ++ loop (x :: acc) xs ++ in ++ List.rev (loop [] xs) ++ ++(* This is present in OCaml 4.04, so we can remove it when ++ * we depend on OCaml >= 4.04. ++ *) ++let sort_uniq ?(cmp = Pervasives.compare) xs = ++ let xs = List.sort cmp xs in ++ let xs = uniq ~cmp xs in ++ xs ++ + let chan = ref Pervasives.stdout + let pr fs = ksprintf (fun str -> output_string !chan str) fs + +@@ -3100,6 +3119,30 @@ let () = + name + ) handle_calls; + ++ (* Closures must be uniquely named across all calls. *) ++ let () = ++ let all_args = ++ List.flatten (List.map (fun (_, { args }) -> args) handle_calls) in ++ let h = Hashtbl.create 13 in ++ List.iter ( ++ function ++ | Closure { cbname; cbargs } -> ++ (try ++ (* If we've already added this name to the hash, check ++ * closure args are identical. ++ *) ++ let other_cbargs = Hashtbl.find h cbname in ++ if cbargs <> other_cbargs then ++ failwithf "%s: Closure has different arguments across methods" ++ cbname ++ with Not_found -> ++ (* Otherwise add it to the hash. *) ++ Hashtbl.add h cbname cbargs ++ ) ++ | _ -> () ++ ) all_args ++ in ++ + (* !may_set_error is incompatible with permitted_states != [] because + * an incorrect state will result in set_error being called by the + * generated wrapper. It is also incompatible with RUint. +@@ -3170,7 +3213,8 @@ let rec name_of_arg = function + | BytesOut (n, len) -> [n; len] + | BytesPersistIn (n, len) -> [n; len] + | BytesPersistOut (n, len) -> [n; len] +-| Closure { cbname } -> [cbname; sprintf "%s_user_data" cbname ] ++| Closure { cbname } -> ++ [ sprintf "%s_callback" cbname; sprintf "%s_user_data" cbname ] + | Flags n -> [n] + | Int n -> [n] + | Int64 n -> [n] +@@ -3232,12 +3276,8 @@ let rec print_arg_list ?(handle = false) ?(valid_flag = false) + if types then pr "size_t "; + pr "%s" len + | Closure { cbname; cbargs } -> +- if types then ( +- pr "int (*%s) " cbname; +- print_arg_list ~valid_flag:true ~user_data:true cbargs; +- ) +- else +- pr "%s" cbname; ++ if types then pr "nbd_%s_callback " cbname; ++ pr "%s_callback" cbname; + pr ", "; + if types then pr "void *"; + pr "%s_user_data" cbname +@@ -3297,6 +3337,24 @@ let print_extern name args ret = + print_call name args ret; + pr ";\n" + ++(* Callback typedefs in *) ++let print_closure_typedefs () = ++ let all_cls = ++ List.map ( ++ fun (_, { args }) -> ++ filter_map (function Closure cl -> Some cl | _ -> None) args ++ ) handle_calls in ++ let all_cls = List.flatten all_cls in ++ let cmp { cbname = n1 } { cbname = n2 } = compare n1 n2 in ++ let unique_cls = sort_uniq ~cmp all_cls in ++ List.iter ( ++ fun { cbname; cbargs } -> ++ pr "typedef int (*nbd_%s_callback) " cbname; ++ print_arg_list ~valid_flag:true ~user_data:true cbargs; ++ pr ";\n"; ++ ) unique_cls; ++ pr "\n" ++ + let print_extern_and_define name args ret = + let name_upper = String.uppercase_ascii name in + print_extern name args ret; +@@ -3355,6 +3413,7 @@ let generate_include_libnbd_h () = + pr "extern int nbd_get_errno (void);\n"; + pr "#define LIBNBD_HAVE_NBD_GET_ERRNO 1\n"; + pr "\n"; ++ print_closure_typedefs (); + List.iter ( + fun (name, { args; ret }) -> print_extern_and_define name args ret + ) handle_calls; +@@ -4845,7 +4904,7 @@ let print_ocaml_binding (name, { args; ret }) = + pr " if (%s_user_data == NULL) caml_raise_out_of_memory ();\n" cbname; + pr " caml_register_generational_global_root (%s_user_data);\n" cbname; + pr " *%s_user_data = %sv;\n" cbname cbname; +- pr " const void *%s = %s_%s_wrapper;\n" cbname name cbname ++ pr " const void *%s_callback = %s_%s_wrapper;\n" cbname name cbname + | OCamlArg (Flags _) -> assert false (* see above *) + | OCamlArg (Int n) -> + pr " int %s = Int_val (%sv);\n" n n +diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c +index e0fd71d..9b249ab 100644 +--- a/generator/states-reply-simple.c ++++ b/generator/states-reply-simple.c +@@ -60,16 +60,16 @@ + case 0: + /* guaranteed by START */ + assert (cmd); +- if (cmd->cb.fn.read) { ++ if (cmd->cb.fn.chunk) { + int error = 0; + + assert (cmd->error == 0); +- if (cmd->cb.fn.read (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, +- cmd->cb.fn_user_data, +- cmd->data, cmd->count, +- cmd->offset, LIBNBD_READ_DATA, &error) == -1) ++ if (cmd->cb.fn.chunk (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, ++ cmd->cb.fn_user_data, ++ cmd->data, cmd->count, ++ cmd->offset, LIBNBD_READ_DATA, &error) == -1) + cmd->error = error ? error : EPROTO; +- cmd->cb.fn.read = NULL; /* because we've freed it */ ++ cmd->cb.fn.chunk = NULL; /* because we've freed it */ + } + + SET_NEXT_STATE (%^FINISH_COMMAND); +diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c +index ff5b727..cdd9f10 100644 +--- a/generator/states-reply-structured.c ++++ b/generator/states-reply-structured.c +@@ -304,7 +304,7 @@ valid_flags (struct nbd_handle *h) + offset, cmd->offset, cmd->count); + return 0; + } +- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read) { ++ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) { + int scratch = error; + unsigned valid = valid_flags (h); + +@@ -312,13 +312,13 @@ valid_flags (struct nbd_handle *h) + * current error rather than any earlier one. If the callback fails + * without setting errno, then use the server's error below. + */ +- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data, +- cmd->data + (offset - cmd->offset), +- 0, offset, LIBNBD_READ_ERROR, &scratch) == -1) ++ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, ++ cmd->data + (offset - cmd->offset), ++ 0, offset, LIBNBD_READ_ERROR, &scratch) == -1) + if (cmd->error == 0) + cmd->error = scratch; + if (valid & LIBNBD_CALLBACK_FREE) +- cmd->cb.fn.read = NULL; /* because we've freed it */ ++ cmd->cb.fn.chunk = NULL; /* because we've freed it */ + } + } + +@@ -398,18 +398,18 @@ valid_flags (struct nbd_handle *h) + offset = be64toh (h->sbuf.sr.payload.offset_data.offset); + + assert (cmd); /* guaranteed by CHECK */ +- if (cmd->cb.fn.read) { ++ if (cmd->cb.fn.chunk) { + int error = cmd->error; + unsigned valid = valid_flags (h); + +- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data, +- cmd->data + (offset - cmd->offset), +- length - sizeof offset, offset, ++ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, ++ cmd->data + (offset - cmd->offset), ++ length - sizeof offset, offset, + LIBNBD_READ_DATA, &error) == -1) + if (cmd->error == 0) + cmd->error = error ? error : EPROTO; + if (valid & LIBNBD_CALLBACK_FREE) +- cmd->cb.fn.read = NULL; /* because we've freed it */ ++ cmd->cb.fn.chunk = NULL; /* because we've freed it */ + } + + SET_NEXT_STATE (%FINISH); +@@ -463,18 +463,18 @@ valid_flags (struct nbd_handle *h) + * them as an extension, and this works even when length == 0. + */ + memset (cmd->data + offset, 0, length); +- if (cmd->cb.fn.read) { ++ if (cmd->cb.fn.chunk) { + int error = cmd->error; + unsigned valid = valid_flags (h); + +- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data, +- cmd->data + offset, length, +- cmd->offset + offset, +- LIBNBD_READ_HOLE, &error) == -1) ++ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, ++ cmd->data + offset, length, ++ cmd->offset + offset, ++ LIBNBD_READ_HOLE, &error) == -1) + if (cmd->error == 0) + cmd->error = error ? error : EPROTO; + if (valid & LIBNBD_CALLBACK_FREE) +- cmd->cb.fn.read = NULL; /* because we've freed it */ ++ cmd->cb.fn.chunk = NULL; /* because we've freed it */ + } + + SET_NEXT_STATE(%FINISH); +@@ -548,10 +548,10 @@ valid_flags (struct nbd_handle *h) + if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent) + cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, + NULL, 0, NULL, 0, NULL); +- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read) +- cmd->cb.fn.read (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, +- NULL, 0, 0, 0, NULL); +- cmd->cb.fn.read = NULL; ++ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) ++ cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, ++ NULL, 0, 0, 0, NULL); ++ cmd->cb.fn.chunk = NULL; + SET_NEXT_STATE (%^FINISH_COMMAND); + } + else { +diff --git a/generator/states-reply.c b/generator/states-reply.c +index 078d67f..09adfed 100644 +--- a/generator/states-reply.c ++++ b/generator/states-reply.c +@@ -168,14 +168,14 @@ save_reply_state (struct nbd_handle *h) + retire = cmd->type == NBD_CMD_DISC; + + /* Notify the user */ +- if (cmd->cb.callback) { ++ if (cmd->cb.completion) { + int error = cmd->error; + int r; + + assert (cmd->type != NBD_CMD_DISC); +- r = cmd->cb.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, +- cmd->cb.user_data, &error); +- cmd->cb.callback = NULL; /* because we've freed it */ ++ r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, ++ cmd->cb.user_data, &error); ++ cmd->cb.completion = NULL; /* because we've freed it */ + switch (r) { + case -1: + if (error) +diff --git a/generator/states.c b/generator/states.c +index 654e4c8..9ed57ae 100644 +--- a/generator/states.c ++++ b/generator/states.c +@@ -121,14 +121,14 @@ void abort_commands (struct nbd_handle *h, + bool retire = cmd->type == NBD_CMD_DISC; + + next = cmd->next; +- if (cmd->cb.callback) { ++ if (cmd->cb.completion) { + int error = cmd->error ? cmd->error : ENOTCONN; + int r; + + assert (cmd->type != NBD_CMD_DISC); +- r = cmd->cb.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, +- cmd->cb.user_data, &error); +- cmd->cb.callback = NULL; /* because we've freed it */ ++ r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, ++ cmd->cb.user_data, &error); ++ cmd->cb.completion = NULL; /* because we've freed it */ + switch (r) { + case -1: + if (error) +diff --git a/lib/aio.c b/lib/aio.c +index 1c11dbd..c141de6 100644 +--- a/lib/aio.c ++++ b/lib/aio.c +@@ -35,12 +35,12 @@ nbd_internal_retire_and_free_command (struct command *cmd) + if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent) + cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, + NULL, 0, NULL, 0, NULL); +- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read) +- cmd->cb.fn.read (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, +- NULL, 0, 0, 0, NULL); +- if (cmd->cb.callback) +- cmd->cb.callback (LIBNBD_CALLBACK_FREE, cmd->cb.user_data, +- NULL); ++ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) ++ cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, ++ NULL, 0, 0, 0, NULL); ++ if (cmd->cb.completion) ++ cmd->cb.completion (LIBNBD_CALLBACK_FREE, cmd->cb.user_data, ++ NULL); + + free (cmd); + } +diff --git a/lib/debug.c b/lib/debug.c +index 7784bd9..f4b374d 100644 +--- a/lib/debug.c ++++ b/lib/debug.c +@@ -40,12 +40,12 @@ nbd_unlocked_get_debug (struct nbd_handle *h) + + int + nbd_unlocked_set_debug_callback (struct nbd_handle *h, +- debug_fn debug_fn, void *data) ++ nbd_debug_callback debug_callback, void *data) + { +- if (h->debug_fn) ++ if (h->debug_callback) + /* ignore return value */ +- h->debug_fn (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL); +- h->debug_fn = debug_fn; ++ h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL); ++ h->debug_callback = debug_callback; + h->debug_data = data; + return 0; + } +@@ -76,9 +76,9 @@ nbd_internal_debug (struct nbd_handle *h, const char *fs, ...) + if (r == -1) + goto out; + +- if (h->debug_fn) ++ if (h->debug_callback) + /* ignore return value */ +- h->debug_fn (LIBNBD_CALLBACK_VALID, h->debug_data, context, msg); ++ h->debug_callback (LIBNBD_CALLBACK_VALID, h->debug_data, context, msg); + else + fprintf (stderr, "libnbd: debug: %s: %s\n", context ? : "unknown", msg); + out: +diff --git a/lib/handle.c b/lib/handle.c +index a9ade3d..1360079 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -105,9 +105,9 @@ nbd_close (struct nbd_handle *h) + return; + + /* Free user callbacks first. */ +- if (h->debug_fn) +- h->debug_fn (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL); +- h->debug_fn = NULL; ++ if (h->debug_callback) ++ h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL); ++ h->debug_callback = NULL; + + free (h->bs_entries); + for (m = h->meta_contexts; m != NULL; m = m_next) { +diff --git a/lib/internal.h b/lib/internal.h +index 90ce6aa..d85fb4b 100644 +--- a/lib/internal.h ++++ b/lib/internal.h +@@ -47,7 +47,6 @@ + struct meta_context; + struct socket; + struct command; +-typedef int (*debug_fn) (unsigned, void *, const char *, const char *); + + struct nbd_handle { + /* Lock protecting concurrent access to the handle. */ +@@ -80,7 +79,7 @@ struct nbd_handle { + + /* For debugging. */ + bool debug; +- debug_fn debug_fn; ++ nbd_debug_callback debug_callback; + void *debug_data; + + /* State machine. +@@ -248,23 +247,14 @@ struct socket { + const struct socket_ops *ops; + }; + +-typedef int (*extent_fn) (unsigned valid_flag, void *user_data, +- const char *metacontext, uint64_t offset, +- uint32_t *entries, size_t nr_entries, int *error); +-typedef int (*read_fn) (unsigned valid_flag, void *user_data, +- const void *buf, size_t count, +- uint64_t offset, unsigned status, int *error); +-typedef int (*callback_fn) (unsigned valid_flag, void *user_data, +- int *error); +- + struct command_cb { + union { +- extent_fn extent; +- read_fn read; ++ nbd_extent_callback extent; ++ nbd_chunk_callback chunk; + } fn; + void *fn_user_data; /* associated with one of the fn callbacks above */ +- callback_fn callback; +- void *user_data; /* associated with the callback function */ ++ nbd_completion_callback completion; ++ void *user_data; /* associated with the completion callback */ + }; + + struct command { +diff --git a/lib/rw.c b/lib/rw.c +index 382cfb9..51ee691 100644 +--- a/lib/rw.c ++++ b/lib/rw.c +@@ -60,12 +60,13 @@ nbd_unlocked_pread (struct nbd_handle *h, void *buf, + int + nbd_unlocked_pread_structured (struct nbd_handle *h, void *buf, + size_t count, uint64_t offset, +- read_fn read, void *user_data, uint32_t flags) ++ nbd_chunk_callback chunk, void *user_data, ++ uint32_t flags) + { + int64_t cookie; + + cookie = nbd_unlocked_aio_pread_structured (h, buf, count, offset, +- read, user_data, flags); ++ chunk, user_data, flags); + if (cookie == -1) + return -1; + +@@ -145,7 +146,8 @@ nbd_unlocked_zero (struct nbd_handle *h, + int + nbd_unlocked_block_status (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- extent_fn extent, void *user_data, uint32_t flags) ++ nbd_extent_callback extent, void *user_data, ++ uint32_t flags) + { + int64_t cookie; + +@@ -255,10 +257,11 @@ nbd_unlocked_aio_pread (struct nbd_handle *h, void *buf, + int64_t + nbd_unlocked_aio_pread_callback (struct nbd_handle *h, void *buf, + size_t count, uint64_t offset, +- callback_fn callback, void *user_data, ++ nbd_completion_callback completion, ++ void *user_data, + uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + /* We could silently accept flag DF, but it really only makes sense + * with callbacks, because otherwise there is no observable change +@@ -276,11 +279,11 @@ nbd_unlocked_aio_pread_callback (struct nbd_handle *h, void *buf, + int64_t + nbd_unlocked_aio_pread_structured (struct nbd_handle *h, void *buf, + size_t count, uint64_t offset, +- read_fn read, void *user_data, ++ nbd_chunk_callback chunk, void *user_data, + uint32_t flags) + { + return nbd_unlocked_aio_pread_structured_callback (h, buf, count, offset, +- read, user_data, ++ chunk, user_data, + NULL, NULL, + flags); + } +@@ -288,15 +291,15 @@ nbd_unlocked_aio_pread_structured (struct nbd_handle *h, void *buf, + int64_t + nbd_unlocked_aio_pread_structured_callback (struct nbd_handle *h, void *buf, + size_t count, uint64_t offset, +- read_fn read, ++ nbd_chunk_callback chunk, + void *read_user_data, +- callback_fn callback, ++ nbd_completion_callback completion, + void *callback_user_data, + uint32_t flags) + { +- struct command_cb cb = { .fn.read = read, ++ struct command_cb cb = { .fn.chunk = chunk, + .fn_user_data = read_user_data, +- .callback = callback, ++ .completion = completion, + .user_data = callback_user_data, }; + + if ((flags & ~LIBNBD_CMD_FLAG_DF) != 0) { +@@ -326,10 +329,11 @@ nbd_unlocked_aio_pwrite (struct nbd_handle *h, const void *buf, + int64_t + nbd_unlocked_aio_pwrite_callback (struct nbd_handle *h, const void *buf, + size_t count, uint64_t offset, +- callback_fn callback, void *user_data, ++ nbd_completion_callback completion, ++ void *user_data, + uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + if (nbd_unlocked_read_only (h) == 1) { + set_error (EINVAL, "server does not support write operations"); +@@ -358,10 +362,12 @@ nbd_unlocked_aio_flush (struct nbd_handle *h, uint32_t flags) + } + + int64_t +-nbd_unlocked_aio_flush_callback (struct nbd_handle *h, callback_fn callback, +- void *user_data, uint32_t flags) ++nbd_unlocked_aio_flush_callback (struct nbd_handle *h, ++ nbd_completion_callback completion, ++ void *user_data, ++ uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + if (nbd_unlocked_can_flush (h) != 1) { + set_error (EINVAL, "server does not support flush operations"); +@@ -388,10 +394,11 @@ nbd_unlocked_aio_trim (struct nbd_handle *h, + int64_t + nbd_unlocked_aio_trim_callback (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- callback_fn callback, void *user_data, ++ nbd_completion_callback completion, ++ void *user_data, + uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + if (nbd_unlocked_read_only (h) == 1) { + set_error (EINVAL, "server does not support write operations"); +@@ -428,10 +435,11 @@ nbd_unlocked_aio_cache (struct nbd_handle *h, + int64_t + nbd_unlocked_aio_cache_callback (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- callback_fn callback, void *user_data, ++ nbd_completion_callback completion, ++ void *user_data, + uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + /* Actually according to the NBD protocol document, servers do exist + * that support NBD_CMD_CACHE but don't advertise the +@@ -462,10 +470,11 @@ nbd_unlocked_aio_zero (struct nbd_handle *h, + int64_t + nbd_unlocked_aio_zero_callback (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- callback_fn callback, void *user_data, ++ nbd_completion_callback completion, ++ void *user_data, + uint32_t flags) + { +- struct command_cb cb = { .callback = callback, .user_data = user_data, }; ++ struct command_cb cb = { .completion = completion, .user_data = user_data, }; + + if (nbd_unlocked_read_only (h) == 1) { + set_error (EINVAL, "server does not support write operations"); +@@ -495,7 +504,7 @@ nbd_unlocked_aio_zero_callback (struct nbd_handle *h, + int64_t + nbd_unlocked_aio_block_status (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- extent_fn extent, void *user_data, ++ nbd_extent_callback extent, void *user_data, + uint32_t flags) + { + return nbd_unlocked_aio_block_status_callback (h, count, offset, +@@ -507,15 +516,15 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h, + int64_t + nbd_unlocked_aio_block_status_callback (struct nbd_handle *h, + uint64_t count, uint64_t offset, +- extent_fn extent, ++ nbd_extent_callback extent, + void *extent_user_data, +- callback_fn callback, ++ nbd_completion_callback completion, + void *callback_user_data, + uint32_t flags) + { + struct command_cb cb = { .fn.extent = extent, + .fn_user_data = extent_user_data, +- .callback = callback, ++ .completion = completion, + .user_data = callback_user_data }; + + if (!h->structured_replies) { +-- +2.22.0 + diff --git a/0008-generator-Remove-some-extraneous-blank-lines-from-ge.patch b/0008-generator-Remove-some-extraneous-blank-lines-from-ge.patch new file mode 100644 index 0000000..65abc7a --- /dev/null +++ b/0008-generator-Remove-some-extraneous-blank-lines-from-ge.patch @@ -0,0 +1,29 @@ +From 6a4724eba9685ee56ba0509b033b83670edd5328 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 15:07:07 +0100 +Subject: [PATCH 08/11] generator: Remove some extraneous blank lines from + generated libnbd.h file. + +--- + generator/generator | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/generator/generator b/generator/generator +index 6f89792..4de79ca 100755 +--- a/generator/generator ++++ b/generator/generator +@@ -3417,11 +3417,9 @@ let generate_include_libnbd_h () = + List.iter ( + fun (name, { args; ret }) -> print_extern_and_define name args ret + ) handle_calls; +- pr "\n"; + List.iter ( + fun (ns, ctxts) -> print_ns ns ctxts + ) metadata_namespaces; +- pr "\n"; + pr "#ifdef __cplusplus\n"; + pr "}\n"; + pr "#endif\n"; +-- +2.22.0 + diff --git a/0009-generator-Add-link-to-documentation-in-libnbd.h.patch b/0009-generator-Add-link-to-documentation-in-libnbd.h.patch new file mode 100644 index 0000000..315fe81 --- /dev/null +++ b/0009-generator-Add-link-to-documentation-in-libnbd.h.patch @@ -0,0 +1,33 @@ +From aa44163862c33cd261403ae2b875918582c872ce Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 15:09:15 +0100 +Subject: [PATCH 09/11] generator: Add link to documentation in + +We do the same sort of thing in libguestfs. It helps people to find +the documentation if their first contact with the library is through +seeing the header file. +--- + generator/generator | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/generator/generator b/generator/generator +index 4de79ca..25aeb00 100755 +--- a/generator/generator ++++ b/generator/generator +@@ -3386,6 +3386,13 @@ let generate_include_libnbd_h () = + pr "#ifndef LIBNBD_H\n"; + pr "#define LIBNBD_H\n"; + pr "\n"; ++ pr "/* This is the public interface to libnbd, a client library for\n"; ++ pr " * accessing Network Block Device (NBD) servers.\n"; ++ pr " *\n"; ++ pr " * Please read the libnbd(3) and libnbd-api(3) manual pages to\n"; ++ pr " * find out how to use this library.\n"; ++ pr " */\n"; ++ pr "\n"; + pr "#include \n"; + pr "#include \n"; + pr "#include \n"; +-- +2.22.0 + diff --git a/0010-build-Add-.-configure-disable-ocaml-to-disable-OCaml.patch b/0010-build-Add-.-configure-disable-ocaml-to-disable-OCaml.patch new file mode 100644 index 0000000..3b395f6 --- /dev/null +++ b/0010-build-Add-.-configure-disable-ocaml-to-disable-OCaml.patch @@ -0,0 +1,50 @@ +From c05f1005c2629237843db9c0830ba40d08b5516e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 15:17:53 +0100 +Subject: [PATCH 10/11] build: Add ./configure --disable-ocaml to disable OCaml + bindings. + +This can be used to disable the OCaml language bindings if you don't +want to build those. The OCaml toplevel is still needed to run the +generator, in particular in the case where you want to build from git. +--- + configure.ac | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8c47e61..ade8ab0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -197,10 +197,6 @@ dnl bindings. + AC_PROG_OCAML + AC_PROG_FINDLIB + AM_CONDITIONAL([HAVE_OCAML_TOPLEVEL],[test "x$OCAML" != "xno"]) +-AM_CONDITIONAL([HAVE_OCAML], +- [test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno"]) +-AM_CONDITIONAL([HAVE_OCAMLOPT], +- [test "x$OCAMLOPT" != "xno" && test "x$OCAMLFIND" != "xno"]) + + dnl Flags we want to pass to every OCaml compiler call. + OCAML_WARN_ERROR="-warn-error CDEFLMPSUVYZX+52-3" +@@ -208,6 +204,18 @@ AC_SUBST([OCAML_WARN_ERROR]) + OCAML_FLAGS="-g -annot -safe-string" + AC_SUBST([OCAML_FLAGS]) + ++dnl Note this only disables the OCaml bindings. ++AC_ARG_ENABLE([ocaml], ++ AS_HELP_STRING([--disable-ocaml], [disable OCaml language bindings]), ++ [], ++ [enable_ocaml=yes]) ++AM_CONDITIONAL([HAVE_OCAML], ++ [test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && \ ++ test "x$enable_ocaml" = "xyes"]) ++AM_CONDITIONAL([HAVE_OCAMLOPT], ++ [test "x$OCAMLOPT" != "xno" && test "x$OCAMLFIND" != "xno" && \ ++ test "x$enable_ocaml" = "xyes"]) ++ + dnl Python, optional for the Python bindings and shell. + PYTHON_PREFIX= + PYTHON_VERSION= +-- +2.22.0 + diff --git a/0011-ocaml-Add-make-install-rule.patch b/0011-ocaml-Add-make-install-rule.patch new file mode 100644 index 0000000..7d17a3c --- /dev/null +++ b/0011-ocaml-Add-make-install-rule.patch @@ -0,0 +1,42 @@ +From aa54c46d5fdd9a68ae2237713d5086ecb91235f9 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 3 Aug 2019 15:20:50 +0100 +Subject: [PATCH 11/11] ocaml: Add make install rule. + +This installs the OCaml bindings into $(DESTDIR). If you don't want +this then use ./configure --disable-ocaml. +--- + ocaml/Makefile.am | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am +index bae9e58..c69b5bd 100644 +--- a/ocaml/Makefile.am ++++ b/ocaml/Makefile.am +@@ -103,4 +103,23 @@ endif + $(OCAMLFIND) ocamldep $^ > $@ + -include .depend + ++# Run ocamlfind to perform the install. ocamlfind refuses to install ++# the package if it is already installed, so remove the old package ++# first. ++data_hook_files = META *.so *.a *.cma *.cmi $(srcdir)/*.mli ++if HAVE_OCAMLOPT ++data_hook_files += *.cmx *.cmxa ++endif ++ ++install-data-hook: ++ mkdir -p $(DESTDIR)$(OCAMLLIB) ++ mkdir -p $(DESTDIR)$(OCAMLLIB)/stublibs ++ rm -rf $(DESTDIR)$(OCAMLLIB)/nbd ++ rm -rf $(DESTDIR)$(OCAMLLIB)/stublibs/dllmlnbd.so* ++ $(OCAMLFIND) install \ ++ -ldconf ignore -destdir $(DESTDIR)$(OCAMLLIB) \ ++ nbd \ ++ $(data_hook_files) ++ rm $(DESTDIR)$(OCAMLLIB)/nbd/libnbdocaml.a ++ + endif HAVE_OCAML +-- +2.22.0 + diff --git a/libnbd.spec b/libnbd.spec index 13fd2af..3579de5 100644 --- a/libnbd.spec +++ b/libnbd.spec @@ -2,14 +2,14 @@ %global verify_tarball_signature 1 # If there are patches which touch autotools files, set this to 1. -%global patches_touch_autotools %{nil} +%global patches_touch_autotools 1 # The source directory. %global source_directory 0.x-unstable-api Name: libnbd Version: 0.9.6 -Release: 1%{?dist} +Release: 2%{?dist} Summary: NBD client library in userspace License: LGPLv2+ @@ -23,7 +23,17 @@ Source1: http://libguestfs.org/download/libnbd/%{source_directory}/%{name Source2: libguestfs.keyring # Patches. -# (none) +Patch0001: 0001-TODO-Mark-some-items-done.patch +Patch0002: 0002-tests-Make-sure-errors-test-uses-serialized-nbdkit.patch +Patch0003: 0003-tests-Add-some-basic-compile-tests-inspired-by-nbdki.patch +Patch0004: 0004-Fix-compilation-with-C.patch +Patch0005: 0005-run-Set-MALLOC_CHECK_-1-when-using-.-run-or-running-.patch +Patch0006: 0006-include-Remove-unused-definition-of-nbd_close_callba.patch +Patch0007: 0007-generator-Generate-typedefs-automatically-for-Closur.patch +Patch0008: 0008-generator-Remove-some-extraneous-blank-lines-from-ge.patch +Patch0009: 0009-generator-Add-link-to-documentation-in-libnbd.h.patch +Patch0010: 0010-build-Add-.-configure-disable-ocaml-to-disable-OCaml.patch +Patch0011: 0011-ocaml-Add-make-install-rule.patch %if 0%{patches_touch_autotools} BuildRequires: autoconf, automake, libtool @@ -33,17 +43,25 @@ BuildRequires: autoconf, automake, libtool BuildRequires: gnupg2 %endif +# For the core library. BuildRequires: gcc BuildRequires: /usr/bin/pod2man BuildRequires: gnutls-devel -BuildRequires: python3-devel BuildRequires: libxml2-devel +# For the Python 3 bindings. +BuildRequires: python3-devel + +# For the OCaml bindings. +BuildRequires: ocaml +BuildRequires: ocaml-findlib-devel + # Only for running the test suite. BuildRequires: gnutls-utils BuildRequires: nbdkit BuildRequires: nbd BuildRequires: qemu-img +BuildRequires: gcc-c++ %description @@ -77,6 +95,26 @@ Requires: %{name}%{?_isa} = %{version}-%{release} This package contains development headers for %{name}. +%package -n ocaml-%{name} +Summary: OCaml language bindings for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + + +%description -n ocaml-%{name} +This package contains OCaml language bindings for %{name}. + + +%package -n ocaml-%{name}-devel +Summary: OCaml language development package for %{name} +Requires: ocaml-%{name}%{?_isa} = %{version}-%{release} + + +%description -n ocaml-%{name}-devel +This package contains OCaml language development package for +%{name}. Install this if you want to compile OCaml software which +uses %{name}. + + %package -n python3-%{name} Summary: Python 3 bindings for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} @@ -107,7 +145,8 @@ autoreconf -i --disable-static \ --with-tls-priority=@LIBNBD,SYSTEM \ PYTHON=%{__python3} \ - --enable-python + --enable-python \ + --enable-ocaml make %{?_smp_mflags} @@ -154,6 +193,26 @@ make %{?_smp_mflags} check || { %{_mandir}/man3/libnbd-api.3* +%files -n ocaml-%{name} +%{_libdir}/ocaml/nbd +%exclude %{_libdir}/ocaml/nbd/*.a +%exclude %{_libdir}/ocaml/nbd/*.cmxa +%exclude %{_libdir}/ocaml/nbd/*.cmx +%exclude %{_libdir}/ocaml/nbd/*.mli +%{_libdir}/ocaml/stublibs/dllmlnbd.so +%{_libdir}/ocaml/stublibs/dllmlnbd.so.owner + + +%files -n ocaml-%{name}-devel +%doc ocaml/examples/*.ml +%license ocaml/examples/LICENSE-FOR-EXAMPLES +%{_libdir}/ocaml/nbd/*.a +%{_libdir}/ocaml/nbd/*.cmxa +%{_libdir}/ocaml/nbd/*.cmx +%{_libdir}/ocaml/nbd/*.mli +#%{_mandir}/man3/libnbd-ocaml.3* + + %files -n python3-%{name} %{python3_sitearch}/libnbdmod*.so %{python3_sitearch}/nbd.py @@ -164,6 +223,10 @@ make %{?_smp_mflags} check || { %changelog +* Sat Aug 3 2019 Richard W.M. Jones - 0.9.6-2 +- Add all upstream patches since 0.9.6 was released. +- Package the ocaml bindings into a subpackage. + * Tue Jul 30 2019 Richard W.M. Jones - 0.9.6-1 - New upstream verison 0.9.6.