---
.gitignore | 2 +
Makefile.am | 1 +
TODO | 6 --
configure.ac | 1 +
cp/Makefile.am | 52 +++++++++++++++
cp/nbdcp.c | 84 +++++++++++++++++++++++
cp/nbdcp.pod | 177 +++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 317 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7536021..38923db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,8 @@ Makefile.in
/config.status
/config.sub
/configure
+/cp/nbdcp
+/cp/nbdcp.1
/depcomp
/docs/*.1
/docs/*.3
diff --git a/Makefile.am b/Makefile.am
index 568e735..ed40173 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,6 +39,7 @@ SUBDIRS = \
tests \
python \
sh \
+ cp \
fuse \
ocaml \
ocaml/examples \
diff --git a/TODO b/TODO
index 5c97db0..3a6540d 100644
--- a/TODO
+++ b/TODO
@@ -7,8 +7,6 @@ Bindings in other languages.
Example code integrating with ppoll, pollfd, APR pollset (and others?).
-Example command line utils to copy in/out (like qemu-img convert).
-
NBD_OPT_INFO mode (like qemu-nbd -L).
NBD resize extension.
@@ -22,10 +20,6 @@ Performance: Chart it over various buffer sizes and threads, as that
Examine other fuzzers:
https://gitlab.com/akihe/radamsa
-Should we ship a "nbdcp" copying tool?
- - Could upload, download or copy between servers.
- - Duplicates functionality already available in qemu-img convert.
-
nbdfuse:
- If you write beyond the end of the virtual file, it returns EIO.
- Implement trim/discard.
diff --git a/configure.ac b/configure.ac
index 77a9103..c3b8caa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -382,6 +382,7 @@ AC_CONFIG_FILES([sh/nbdsh],
AC_CONFIG_FILES([Makefile
common/include/Makefile
+ cp/Makefile
docs/Makefile
examples/Makefile
fuse/Makefile
diff --git a/cp/Makefile.am b/cp/Makefile.am
new file mode 100644
index 0000000..1f3301c
--- /dev/null
+++ b/cp/Makefile.am
@@ -0,0 +1,52 @@
+# nbd client library in userspace
+# Copyright (C) 2013-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 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
+
+include $(top_srcdir)/subdir-rules.mk
+
+EXTRA_DIST = \
+ nbdcp.pod \
+ $(NULL)
+
+TESTS_ENVIRONMENT = LIBNBD_DEBUG=1
+LOG_COMPILER = $(top_builddir)/run
+TESTS =
+
+bin_PROGRAMS = nbdcp
+
+nbdcp_SOURCES = nbdcp.c
+nbdcp_CPPFLAGS = -I$(top_srcdir)/include
+nbdcp_CFLAGS = $(WARNINGS_CFLAGS)
+nbdcp_LDADD = $(top_builddir)/lib/libnbd.la
+
+if HAVE_POD
+
+man_MANS = \
+ nbdcp.1 \
+ $(NULL)
+
+nbdcp.1: nbdcp.pod $(top_builddir)/podwrapper.pl
+ $(PODWRAPPER) --section=1 --man $@ \
+ --html $(top_builddir)/html/$@.html \
+ $<
+
+endif HAVE_POD
+
+TESTS += \
+ $(NULL)
+
+check-valgrind:
+ LIBNBD_VALGRIND=1 $(MAKE) check
diff --git a/cp/nbdcp.c b/cp/nbdcp.c
new file mode 100644
index 0000000..c06380c
--- /dev/null
+++ b/cp/nbdcp.c
@@ -0,0 +1,84 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <limits.h>
+
+#include <libnbd.h>
+
+#define MAX_REQUEST_SIZE (32 * 1024 * 1024)
+
+static void __attribute__((noreturn))
+usage (FILE *fp, int exitcode)
+{
+ fprintf (fp,
+"\n"
+"Copy between NBD servers and local files:\n"
+"\n"
+" nbdcp XXX\n"
+"\n"
+"Please read the nbdcp(1) manual page for full usage.\n"
+"\n"
+);
+ exit (exitcode);
+}
+
+static void
+display_version (void)
+{
+ printf ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+}
+
+int
+main (int argc, char *argv[])
+{
+ enum {
+ HELP_OPTION = CHAR_MAX + 1,
+ };
+ const char *short_options = "V";
+ const struct option long_options[] = {
+ { "help", no_argument, NULL, HELP_OPTION },
+ { "version", no_argument, NULL, 'V' },
+ { NULL }
+ };
+ int c;
+
+ for (;;) {
+ c = getopt_long (argc, argv, short_options, long_options, NULL);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case HELP_OPTION:
+ usage (stdout, EXIT_SUCCESS);
+
+ case 'V':
+ display_version ();
+ exit (EXIT_SUCCESS);
+
+ default:
+ usage (stderr, EXIT_FAILURE);
+ }
+ }
+
+ exit (EXIT_FAILURE);
+}
diff --git a/cp/nbdcp.pod b/cp/nbdcp.pod
new file mode 100644
index 0000000..d07e02c
--- /dev/null
+++ b/cp/nbdcp.pod
@@ -0,0 +1,177 @@
+=head1 NAME
+
+nbdcp - copy between NBD servers and local files
+
+=head1 SYNOPSIS
+
+ nbdcp [-a|--target-allocation allocated|sparse]
+ [-m|--multi-conn <n>] [-M|--multi-conn-target <n>]
+ [-p|--progress-bar] [-S|--sparse-detect <n>]
+ [-T|--threads <n>] [-z|--target-is-zero]
+ 'nbd://...'|DISK.IMG 'nbd://...'|DISK.IMG
+
+=head1 DESCRIPTION
+
+nbdcp is a utility that can copy quickly between NBD servers and local
+raw format files (or block devices). It can copy:
+
+=over 4
+
+=item from NBD server to file (or block device)
+
+For example, this command copies from the NBD server listening on port
+10809 on C<example.com> to a local file called F<disk.img>:
+
+ nbdcp
nbd://example.com disk.img
+
+=item from file (or block device) to NBD server
+
+For example, this command copies from a local block device F</dev/sda>
+to the NBD server listening on Unix domain socket F</tmp/socket>:
+
+ nbdcp /dev/sda 'nbd+unix:///?socket=/tmp/socket'
+
+=item from NBD server to NBD server
+
+For example this copies between two different exports on the same NBD
+server:
+
+ nbdcp
nbd://example.com/export1 nbd://example.com/export2
+
+=back
+
+This program I<cannot>: copy from file to file (use L<cp(1)> or
+L<dd(1)>), copy to or from formats other than raw (use L<qemu-img(1)>
+convert), or access servers other than NBD servers (also use
+L<qemu-img(1)>).
+
+NBD servers are specified by their URI, following the NBD URI standard
+at
L<https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md>
+
+=head2 Controlling sparseness or preallocation in the target
+
+The options I<-a> (I<--target-allocation>), I<-S>
(I<--sparse-detect>)
+and I<-z> (I<--target-is-zero>) together control sparseness in the
+target file.
+
+By default nbdcp tries to both preserve sparseness from the source and
+will detect runs of allocated zeroes and turn them into sparseness.
+To turn off detection of sparseness use S<C<-S 0>>.
+
+The I<-z> option should be used if and only if you know that the
+target block device is zeroed already. This allows an important
+optimization where nbdcp can skip zeroing or trimming parts of the
+disk that are already zero.
+
+The I<-a> option is used to control the desired final preallocation
+state of the target. The default is S<C<-a sparse>> which makes the
+target as sparse as possible. S<C<-a allocated>> makes the target
+fully allocated.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Display brief command line help and exit.
+
+=item B<-a allocated>
+
+=item B<--target-allocation=allocated>
+
+Make the target fully allocated.
+
+=item B<-a sparse>
+
+=item B<--target-allocation=sparse>
+
+Make the target as sparse as possible. This is the default. See also
+L</Controlling sparseness or preallocation in the target>.
+
+=item B<-m> N
+
+=item B<--multi-conn=>N
+
+Enable NBD multi-conn with up to C<N> connections. Only some
+NBD servers support this but it can greatly improve performance.
+
+The default is to enable multi-conn if we detect that the server
+supports it, with up to 4 connections.
+
+=item B<-M> N
+
+=item B<--multi-conn-target=>N
+
+If you are copying between NBD servers, use I<-m> to control the
+multi-conn setting for the source server, and this option (I<-M>) to
+control the multi-conn setting for the target server.
+
+=item B<-p>
+
+=item B<--progress-bar>
+
+Display a progress bar during copying.
+
+=item B<-p machine:>FD
+
+=item B<--progress-bar=machine:>FD
+
+Write a machine-readable progress bar to file descriptor C<FD>. This
+progress bar prints lines with the format C<COPIED/TOTAL> (where
+C<COPIED> and C<TOTAL> are 64 bit unsigned integers).
+
+=item B<-S 0>
+
+=item B<--sparse-detect=0>
+
+Turn off sparseness detection.
+
+=item B<-S> N
+
+=item B<--sparse-detect=>N
+
+Detect runs of zero bytes of at least size C<N> bytes and turn them
+into sparse blocks on the target (if S<C<-a sparse>> is used).
+This is the default, with a 512 byte block size.
+
+=item B<-T> N
+
+=item B<--threads> N
+
+Use at most C<N> threads when copying. Usually more threads leads to
+better performance, up to the limit of the number of cores on your
+machine and the parallelism of the underlying disk or network. The
+default is to use the number of online processors.
+
+=item B<-z>
+
+=item B<--target-is-zero>
+
+Declare that the target block device contains only zero bytes (or
+sparseness that reads back as zeroes). You must only use this option
+if you are sure that this is true, since it means that nbdcp will
+enable an optimization where it skips zeroing parts of the disk that
+are zero on the source.
+
+=item B<-V>
+
+=item B<--version>
+
+Display the package name and version and exit.
+
+=back
+
+=head1 SEE ALSO
+
+L<qemu-img(1)>,
+L<libnbd(3)>,
+L<nbdsh(1)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones
+
+=head1 COPYRIGHT
+
+Copyright (C) 2020 Red Hat Inc.
--
2.24.1