1224 lines
34 KiB
Diff
1224 lines
34 KiB
Diff
From 90fd39da16256407b9229cd17a830739b03629d6 Mon Sep 17 00:00:00 2001
|
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
Date: Thu, 30 Jun 2022 09:07:27 +0100
|
|
Subject: [PATCH] Add nbddump tool
|
|
|
|
You can already do this operation using:
|
|
|
|
nbdcopy -- $uri - | hexdump -C
|
|
|
|
but that is slow, especially for large, sparse disks. This tool uses
|
|
sparseness information to skip zero sections of the disk, and it has
|
|
nice colourized output.
|
|
|
|
(cherry picked from commit c4107b9a40d6451630dcccf1bf6596c8e56420be)
|
|
---
|
|
.gitignore | 3 +
|
|
Makefile.am | 1 +
|
|
README | 2 +
|
|
bash-completion/Makefile.am | 9 +-
|
|
bash-completion/nbdsh | 6 +
|
|
configure.ac | 1 +
|
|
copy/nbdcopy.pod | 3 +-
|
|
docs/libnbd.pod | 1 +
|
|
dump/Makefile.am | 79 ++++++
|
|
dump/dump-data.sh | 57 +++++
|
|
dump/dump-empty-qcow2.sh | 46 ++++
|
|
dump/dump-pattern.sh | 56 +++++
|
|
dump/dump.c | 464 ++++++++++++++++++++++++++++++++++++
|
|
dump/nbddump.pod | 116 +++++++++
|
|
dump/test-long-options.sh | 35 +++
|
|
dump/test-short-options.sh | 35 +++
|
|
dump/test-version.sh | 33 +++
|
|
fuse/nbdfuse.pod | 1 +
|
|
info/nbdinfo.pod | 1 +
|
|
run.in | 1 +
|
|
sh/nbdsh.pod | 1 +
|
|
21 files changed, 947 insertions(+), 4 deletions(-)
|
|
create mode 100644 dump/Makefile.am
|
|
create mode 100755 dump/dump-data.sh
|
|
create mode 100755 dump/dump-empty-qcow2.sh
|
|
create mode 100755 dump/dump-pattern.sh
|
|
create mode 100644 dump/dump.c
|
|
create mode 100644 dump/nbddump.pod
|
|
create mode 100755 dump/test-long-options.sh
|
|
create mode 100755 dump/test-short-options.sh
|
|
create mode 100755 dump/test-version.sh
|
|
|
|
diff --git a/.gitignore b/.gitignore
|
|
index 498eabc..3771655 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -29,6 +29,7 @@ Makefile.in
|
|
/aclocal.m4
|
|
/autom4te.cache
|
|
/bash-completion/nbdcopy
|
|
+/bash-completion/nbddump
|
|
/bash-completion/nbdfuse
|
|
/bash-completion/nbdinfo
|
|
/common/include/test-array-size
|
|
@@ -57,6 +58,8 @@ Makefile.in
|
|
!/docs/nbd_close.3
|
|
!/docs/nbd_create.pod
|
|
!/docs/nbd_get_err??.3
|
|
+/dump/nbddump
|
|
+/dump/nbddump.1
|
|
/examples/aio-connect-read
|
|
/examples/batched-read-write
|
|
/examples/connect-command
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index 303b95c..9e7a281 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -46,6 +46,7 @@ SUBDIRS = \
|
|
sh \
|
|
info \
|
|
copy \
|
|
+ dump \
|
|
fuse \
|
|
ocaml \
|
|
ocaml/examples \
|
|
diff --git a/README b/README
|
|
index e50c19d..4f9298e 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -23,6 +23,8 @@ The key features are:
|
|
|
|
* Copying tool (nbdcopy) for high performance copying and streaming.
|
|
|
|
+ * Hexdump tool (nbddump) to print NBD content.
|
|
+
|
|
* Query tool (nbdinfo) to query NBD servers.
|
|
|
|
* FUSE support (nbdfuse) to mount NBD in the local filesystem.
|
|
diff --git a/bash-completion/Makefile.am b/bash-completion/Makefile.am
|
|
index 41d7b13..cab8ffb 100644
|
|
--- a/bash-completion/Makefile.am
|
|
+++ b/bash-completion/Makefile.am
|
|
@@ -24,17 +24,20 @@ EXTRA_DIST = \
|
|
|
|
if HAVE_BASH_COMPLETION
|
|
|
|
-bashcomp_DATA = nbdfuse nbdsh
|
|
+bashcomp_DATA = nbddump nbdfuse nbdsh
|
|
|
|
if HAVE_LIBXML2
|
|
bashcomp_DATA += nbdcopy nbdinfo
|
|
endif HAVE_LIBXML2
|
|
|
|
-
|
|
nbdcopy: nbdsh
|
|
rm -f $@
|
|
$(LN_S) $(srcdir)/nbdsh $@
|
|
|
|
+nbddump: nbdsh
|
|
+ rm -f $@
|
|
+ $(LN_S) $(srcdir)/nbdsh $@
|
|
+
|
|
nbdfuse: nbdsh
|
|
rm -f $@
|
|
$(LN_S) $(srcdir)/nbdsh $@
|
|
@@ -43,6 +46,6 @@ nbdinfo: nbdsh
|
|
rm -f $@
|
|
$(LN_S) $(srcdir)/nbdsh $@
|
|
|
|
-CLEANFILES += nbdcopy nbdfuse nbdinfo
|
|
+CLEANFILES += nbdcopy nbddump nbdfuse nbdinfo
|
|
|
|
endif
|
|
diff --git a/bash-completion/nbdsh b/bash-completion/nbdsh
|
|
index a740be9..a342003 100644
|
|
--- a/bash-completion/nbdsh
|
|
+++ b/bash-completion/nbdsh
|
|
@@ -47,6 +47,11 @@ _nbdcopy ()
|
|
_libnbd_command nbdcopy
|
|
}
|
|
|
|
+_nbddump ()
|
|
+{
|
|
+ _libnbd_command nbddump
|
|
+}
|
|
+
|
|
_nbdfuse ()
|
|
{
|
|
_libnbd_command nbdfuse
|
|
@@ -64,6 +69,7 @@ _nbdsh ()
|
|
|
|
# Install the handler function.
|
|
complete -o default -F _nbdcopy nbdcopy
|
|
+complete -o default -F _nbddump nbddump
|
|
complete -o default -F _nbdfuse nbdfuse
|
|
complete -o default -F _nbdinfo nbdinfo
|
|
complete -o default -F _nbdsh nbdsh
|
|
diff --git a/configure.ac b/configure.ac
|
|
index b1bfaac..49ca8ab 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -574,6 +574,7 @@ AC_CONFIG_FILES([Makefile
|
|
common/utils/Makefile
|
|
copy/Makefile
|
|
docs/Makefile
|
|
+ dump/Makefile
|
|
examples/Makefile
|
|
fuse/Makefile
|
|
fuzzing/Makefile
|
|
diff --git a/copy/nbdcopy.pod b/copy/nbdcopy.pod
|
|
index 7fe3fd1..fd10f7c 100644
|
|
--- a/copy/nbdcopy.pod
|
|
+++ b/copy/nbdcopy.pod
|
|
@@ -285,7 +285,7 @@ Some examples follow.
|
|
In this example, L<qemu-nbd(8)> is run as a subprocess. The
|
|
subprocess opens F<disk.qcow2> and exposes it as NBD to nbdcopy.
|
|
nbdcopy streams this to stdout (C<->) into the pipe which is read by
|
|
-L<hexdump(1)>.
|
|
+L<hexdump(1)>. (See also L<nbddump(1)>)
|
|
|
|
=head2 nbdcopy -- [ qemu-nbd -f qcow2 disk.qcow2 ] [ nbdkit memory 1G ]
|
|
|
|
@@ -299,6 +299,7 @@ so this command has no overall effect, but is useful for testing.
|
|
=head1 SEE ALSO
|
|
|
|
L<libnbd(3)>,
|
|
+L<nbddump(1)>,
|
|
L<nbdfuse(1)>,
|
|
L<nbdinfo(1)>,
|
|
L<nbdsh(1)>,
|
|
diff --git a/docs/libnbd.pod b/docs/libnbd.pod
|
|
index 13facc6..076cafb 100644
|
|
--- a/docs/libnbd.pod
|
|
+++ b/docs/libnbd.pod
|
|
@@ -1044,6 +1044,7 @@ L<libnbd-release-notes-1.2(1)>.
|
|
|
|
L<libnbd-security(3)>,
|
|
L<nbdcopy(1)>,
|
|
+L<nbddump(1)>,
|
|
L<nbdfuse(1)>,
|
|
L<nbdinfo(1)>,
|
|
L<nbdsh(1)>,
|
|
diff --git a/dump/Makefile.am b/dump/Makefile.am
|
|
new file mode 100644
|
|
index 0000000..9fd4fed
|
|
--- /dev/null
|
|
+++ b/dump/Makefile.am
|
|
@@ -0,0 +1,79 @@
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2020-2022 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 = \
|
|
+ dump-data.sh \
|
|
+ dump-empty-qcow2.sh \
|
|
+ dump-pattern.sh \
|
|
+ nbddump.pod \
|
|
+ test-long-options.sh \
|
|
+ test-short-options.sh \
|
|
+ test-version.sh \
|
|
+ $(NULL)
|
|
+
|
|
+bin_PROGRAMS = nbddump
|
|
+
|
|
+nbddump_SOURCES = \
|
|
+ dump.c \
|
|
+ $(NULL)
|
|
+nbddump_CPPFLAGS = \
|
|
+ -I$(top_srcdir)/include \
|
|
+ -I$(top_srcdir)/common/include \
|
|
+ -I$(top_srcdir)/common/utils \
|
|
+ $(NULL)
|
|
+nbddump_CFLAGS = \
|
|
+ $(WARNINGS_CFLAGS) \
|
|
+ $(NULL)
|
|
+nbddump_LDADD = \
|
|
+ $(top_builddir)/common/utils/libutils.la \
|
|
+ $(top_builddir)/lib/libnbd.la \
|
|
+ $(NULL)
|
|
+
|
|
+if HAVE_POD
|
|
+
|
|
+man_MANS = \
|
|
+ nbddump.1 \
|
|
+ $(NULL)
|
|
+
|
|
+nbddump.1: nbddump.pod $(top_builddir)/podwrapper.pl
|
|
+ $(PODWRAPPER) --section=1 --man $@ \
|
|
+ --html $(top_builddir)/html/$@.html \
|
|
+ $<
|
|
+
|
|
+endif HAVE_POD
|
|
+
|
|
+TESTS_ENVIRONMENT = \
|
|
+ LIBNBD_DEBUG=1 \
|
|
+ $(MALLOC_CHECKS) \
|
|
+ EXPECTED_VERSION=$(VERSION) \
|
|
+ QEMU_NBD=$(QEMU_NBD) \
|
|
+ $(NULL)
|
|
+LOG_COMPILER = $(top_builddir)/run
|
|
+
|
|
+TESTS = \
|
|
+ dump-data.sh \
|
|
+ dump-empty-qcow2.sh \
|
|
+ dump-pattern.sh \
|
|
+ test-long-options.sh \
|
|
+ test-short-options.sh \
|
|
+ test-version.sh \
|
|
+ $(NULL)
|
|
+
|
|
+check-valgrind:
|
|
+ LIBNBD_VALGRIND=1 $(MAKE) check
|
|
diff --git a/dump/dump-data.sh b/dump/dump-data.sh
|
|
new file mode 100755
|
|
index 0000000..23d09da
|
|
--- /dev/null
|
|
+++ b/dump/dump-data.sh
|
|
@@ -0,0 +1,57 @@
|
|
+#!/usr/bin/env bash
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2020-2022 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
|
|
+
|
|
+. ../tests/functions.sh
|
|
+
|
|
+set -e
|
|
+set -x
|
|
+
|
|
+requires nbdkit --version
|
|
+requires nbdkit data --dump-plugin
|
|
+
|
|
+output=dump-data.out
|
|
+rm -f $output
|
|
+cleanup_fn rm -f $output
|
|
+
|
|
+nbdkit -U - data data='
|
|
+ @32768 1
|
|
+ @65535 "hello, world!"
|
|
+ @17825790 "spanning buffer boundary"
|
|
+ @20000000 0
|
|
+' --run 'nbddump "$uri"' > $output
|
|
+
|
|
+cat $output
|
|
+
|
|
+if [ "$(cat $output)" != '0000000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+*
|
|
+0000008000: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+0000008010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+*
|
|
+000000fff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 |...............h|
|
|
+0000010000: 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 00 00 00 00 |ello, world!....|
|
|
+0000010010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+*
|
|
+00010ffff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 73 70 |..............sp|
|
|
+0001100000: 61 6e 6e 69 6e 67 20 62 75 66 66 65 72 20 62 6f |anning buffer bo|
|
|
+0001100010: 75 6e 64 61 72 79 00 00 00 00 00 00 00 00 00 00 |undary..........|
|
|
+0001100020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+*
|
|
+0001312d00: 00 |. |' ]; then
|
|
+ echo "$0: unexpected output from nbddump command"
|
|
+ exit 1
|
|
+fi
|
|
diff --git a/dump/dump-empty-qcow2.sh b/dump/dump-empty-qcow2.sh
|
|
new file mode 100755
|
|
index 0000000..c9e583b
|
|
--- /dev/null
|
|
+++ b/dump/dump-empty-qcow2.sh
|
|
@@ -0,0 +1,46 @@
|
|
+#!/usr/bin/env bash
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2020-2022 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
|
|
+
|
|
+. ../tests/functions.sh
|
|
+
|
|
+set -e
|
|
+set -x
|
|
+
|
|
+requires $QEMU_NBD --version
|
|
+requires qemu-img --version
|
|
+
|
|
+file=dump-empty-qcow2.qcow2
|
|
+output=dump-empty-qcow2.out
|
|
+rm -f $file $output
|
|
+cleanup_fn rm -f $file $output
|
|
+
|
|
+size=1G
|
|
+
|
|
+# Create a large, empty qcow2 file.
|
|
+qemu-img create -f qcow2 $file $size
|
|
+
|
|
+# Dump it and check the output.
|
|
+nbddump -- [ $QEMU_NBD -r -f qcow2 $file ] > $output
|
|
+cat $output
|
|
+
|
|
+if [ "$(cat $output)" != '0000000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
+*
|
|
+003ffffff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|' ]; then
|
|
+ echo "$0: unexpected output from nbddump command"
|
|
+ exit 1
|
|
+fi
|
|
diff --git a/dump/dump-pattern.sh b/dump/dump-pattern.sh
|
|
new file mode 100755
|
|
index 0000000..e4016a8
|
|
--- /dev/null
|
|
+++ b/dump/dump-pattern.sh
|
|
@@ -0,0 +1,56 @@
|
|
+#!/usr/bin/env bash
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2020-2022 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
|
|
+
|
|
+. ../tests/functions.sh
|
|
+
|
|
+set -e
|
|
+set -x
|
|
+
|
|
+requires nbdkit --version
|
|
+requires nbdkit pattern --dump-plugin
|
|
+
|
|
+output=dump-pattern.out
|
|
+rm -f $output
|
|
+cleanup_fn rm -f $output
|
|
+
|
|
+nbdkit -U - pattern size=299 --run 'nbddump "$uri"' > $output
|
|
+
|
|
+cat $output
|
|
+
|
|
+if [ "$(cat $output)" != '0000000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 |................|
|
|
+0000000010: 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 18 |................|
|
|
+0000000020: 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 28 |....... .......(|
|
|
+0000000030: 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 38 |.......0.......8|
|
|
+0000000040: 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 48 |.......@.......H|
|
|
+0000000050: 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00 58 |.......P.......X|
|
|
+0000000060: 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00 68 |.......`.......h|
|
|
+0000000070: 00 00 00 00 00 00 00 70 00 00 00 00 00 00 00 78 |.......p.......x|
|
|
+0000000080: 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 88 |................|
|
|
+0000000090: 00 00 00 00 00 00 00 90 00 00 00 00 00 00 00 98 |................|
|
|
+00000000a0: 00 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 a8 |................|
|
|
+00000000b0: 00 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 b8 |................|
|
|
+00000000c0: 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 c8 |................|
|
|
+00000000d0: 00 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 d8 |................|
|
|
+00000000e0: 00 00 00 00 00 00 00 e0 00 00 00 00 00 00 00 e8 |................|
|
|
+00000000f0: 00 00 00 00 00 00 00 f0 00 00 00 00 00 00 00 f8 |................|
|
|
+0000000100: 00 00 00 00 00 00 01 00 00 00 00 00 00 00 01 08 |................|
|
|
+0000000110: 00 00 00 00 00 00 01 10 00 00 00 00 00 00 01 18 |................|
|
|
+0000000120: 00 00 00 00 00 00 01 20 00 00 00 |....... ... |' ]; then
|
|
+ echo "$0: unexpected output from nbddump command"
|
|
+ exit 1
|
|
+fi
|
|
diff --git a/dump/dump.c b/dump/dump.c
|
|
new file mode 100644
|
|
index 0000000..76af04c
|
|
--- /dev/null
|
|
+++ b/dump/dump.c
|
|
@@ -0,0 +1,464 @@
|
|
+/* NBD client library in userspace
|
|
+ * Copyright (C) 2020-2022 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 <stdbool.h>
|
|
+#include <stdint.h>
|
|
+#include <inttypes.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <ctype.h>
|
|
+#include <signal.h>
|
|
+#include <limits.h>
|
|
+#include <getopt.h>
|
|
+
|
|
+#include <libnbd.h>
|
|
+
|
|
+#include "minmax.h"
|
|
+#include "rounding.h"
|
|
+#include "version.h"
|
|
+#include "vector.h"
|
|
+
|
|
+DEFINE_VECTOR_TYPE (uint32_vector, uint32_t)
|
|
+
|
|
+static const char *progname;
|
|
+static struct nbd_handle *nbd;
|
|
+static bool colour;
|
|
+static uint64_t limit = UINT64_MAX; /* --length (unlimited by default) */
|
|
+static int64_t size; /* actual size */
|
|
+static bool can_meta_context; /* did we get extent data? */
|
|
+
|
|
+/* See do_connect () */
|
|
+static enum { MODE_URI = 1, MODE_SQUARE_BRACKET } mode;
|
|
+static char **args;
|
|
+
|
|
+/* Read buffer. */
|
|
+static unsigned char buffer[16*1024*1024];
|
|
+
|
|
+static void do_connect (void);
|
|
+static void do_dump (void);
|
|
+static void catch_signal (int);
|
|
+
|
|
+static void __attribute__((noreturn))
|
|
+usage (FILE *fp, int exitcode)
|
|
+{
|
|
+ fprintf (fp,
|
|
+"\n"
|
|
+"Hexdump the content of a disk over NBD:\n"
|
|
+"\n"
|
|
+" nbddump NBD-URI | [ CMD ARGS ... ]\n"
|
|
+"\n"
|
|
+"Other options:\n"
|
|
+"\n"
|
|
+" nbddump --help\n"
|
|
+" nbddump --version\n"
|
|
+"\n"
|
|
+"Examples:\n"
|
|
+"\n"
|
|
+" nbddump nbd://localhost\n"
|
|
+" nbddump -- [ qemu-nbd -r -f qcow2 file.qcow2 ]\n"
|
|
+"\n"
|
|
+"Please read the nbddump(1) manual page for full usage.\n"
|
|
+"\n"
|
|
+);
|
|
+ exit (exitcode);
|
|
+}
|
|
+
|
|
+int
|
|
+main (int argc, char *argv[])
|
|
+{
|
|
+ enum {
|
|
+ HELP_OPTION = CHAR_MAX + 1,
|
|
+ LONG_OPTIONS,
|
|
+ SHORT_OPTIONS,
|
|
+ COLOUR_OPTION,
|
|
+ NO_COLOUR_OPTION,
|
|
+ };
|
|
+ const char *short_options = "n:V";
|
|
+ const struct option long_options[] = {
|
|
+ { "help", no_argument, NULL, HELP_OPTION },
|
|
+ { "long-options", no_argument, NULL, LONG_OPTIONS },
|
|
+ { "short-options", no_argument, NULL, SHORT_OPTIONS },
|
|
+ { "version", no_argument, NULL, 'V' },
|
|
+
|
|
+ { "color", no_argument, NULL, COLOUR_OPTION },
|
|
+ { "colors", no_argument, NULL, COLOUR_OPTION },
|
|
+ { "colour", no_argument, NULL, COLOUR_OPTION },
|
|
+ { "colours", no_argument, NULL, COLOUR_OPTION },
|
|
+ { "no-color", no_argument, NULL, NO_COLOUR_OPTION },
|
|
+ { "no-colors", no_argument, NULL, NO_COLOUR_OPTION },
|
|
+ { "no-colour", no_argument, NULL, NO_COLOUR_OPTION },
|
|
+ { "no-colours", no_argument, NULL, NO_COLOUR_OPTION },
|
|
+ { "length", required_argument, NULL, 'n' },
|
|
+ { "limit", required_argument, NULL, 'n' },
|
|
+ { NULL }
|
|
+ };
|
|
+ int c;
|
|
+ size_t i;
|
|
+
|
|
+ progname = argv[0];
|
|
+ colour = isatty (STDOUT_FILENO);
|
|
+
|
|
+ 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 LONG_OPTIONS:
|
|
+ for (i = 0; long_options[i].name != NULL; ++i) {
|
|
+ if (strcmp (long_options[i].name, "long-options") != 0 &&
|
|
+ strcmp (long_options[i].name, "short-options") != 0)
|
|
+ printf ("--%s\n", long_options[i].name);
|
|
+ }
|
|
+ exit (EXIT_SUCCESS);
|
|
+
|
|
+ case SHORT_OPTIONS:
|
|
+ for (i = 0; short_options[i]; ++i) {
|
|
+ if (short_options[i] != ':' && short_options[i] != '+')
|
|
+ printf ("-%c\n", short_options[i]);
|
|
+ }
|
|
+ exit (EXIT_SUCCESS);
|
|
+
|
|
+ case COLOUR_OPTION:
|
|
+ colour = true;
|
|
+ break;
|
|
+
|
|
+ case NO_COLOUR_OPTION:
|
|
+ colour = false;
|
|
+ break;
|
|
+
|
|
+ case 'n':
|
|
+ /* XXX Allow human sizes here. */
|
|
+ if (sscanf (optarg, "%" SCNu64, &limit) != 1) {
|
|
+ fprintf (stderr, "%s: could not parse --length option: %s\n",
|
|
+ progname, optarg);
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 'V':
|
|
+ display_version ("nbddump");
|
|
+ exit (EXIT_SUCCESS);
|
|
+
|
|
+ default:
|
|
+ usage (stderr, EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Is it a URI or subprocess? */
|
|
+ if (argc - optind >= 3 &&
|
|
+ strcmp (argv[optind], "[") == 0 &&
|
|
+ strcmp (argv[argc-1], "]") == 0) {
|
|
+ mode = MODE_SQUARE_BRACKET;
|
|
+ argv[argc-1] = NULL;
|
|
+ args = &argv[optind+1];
|
|
+ }
|
|
+ else if (argc - optind == 1) {
|
|
+ mode = MODE_URI;
|
|
+ args = &argv[optind];
|
|
+ }
|
|
+ else {
|
|
+ usage (stderr, EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ /* Open the NBD side. */
|
|
+ nbd = nbd_create ();
|
|
+ if (nbd == NULL) {
|
|
+ fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+ nbd_set_uri_allow_local_file (nbd, true); /* Allow ?tls-psk-file. */
|
|
+ nbd_add_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
|
|
+
|
|
+ /* Connect to the server. */
|
|
+ do_connect ();
|
|
+ can_meta_context =
|
|
+ nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION) > 0;
|
|
+
|
|
+ /* Get the size. */
|
|
+ size = nbd_get_size (nbd);
|
|
+ if (size == -1) {
|
|
+ fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ /* Before dumping, make sure we restore the terminal on ^C etc. */
|
|
+ signal (SIGINT, catch_signal);
|
|
+ signal (SIGQUIT, catch_signal);
|
|
+ signal (SIGTERM, catch_signal);
|
|
+ signal (SIGHUP, catch_signal);
|
|
+
|
|
+ /* Dump the content. */
|
|
+ do_dump ();
|
|
+
|
|
+ nbd_shutdown (nbd, 0);
|
|
+ nbd_close (nbd);
|
|
+
|
|
+ exit (EXIT_SUCCESS);
|
|
+}
|
|
+
|
|
+/* Connect the handle to the server. */
|
|
+static void
|
|
+do_connect (void)
|
|
+{
|
|
+ int r;
|
|
+
|
|
+ switch (mode) {
|
|
+ case MODE_URI: /* NBD-URI */
|
|
+ r = nbd_connect_uri (nbd, args[0]);
|
|
+ break;
|
|
+
|
|
+ case MODE_SQUARE_BRACKET: /* [ CMD ARGS ... ] */
|
|
+ r = nbd_connect_systemd_socket_activation (nbd, args);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ abort ();
|
|
+ }
|
|
+
|
|
+ if (r == -1) {
|
|
+ fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Various ANSI colours, suppressed if --no-colour / not tty output. */
|
|
+static void
|
|
+ansi_restore (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[0m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+ansi_blue (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[1;34m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+ansi_green (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[0;32m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+ansi_magenta (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[1;35m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+ansi_red (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[1;31m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+ansi_grey (void)
|
|
+{
|
|
+ if (colour)
|
|
+ fputs ("\033[0;90m", stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+catch_signal (int sig)
|
|
+{
|
|
+ printf ("\n");
|
|
+ ansi_restore ();
|
|
+ fflush (stdout);
|
|
+ _exit (EXIT_FAILURE);
|
|
+}
|
|
+
|
|
+/* Read the extent map for the next block and return true if it is all
|
|
+ * zeroes. This is conservative and returns false if we did not get
|
|
+ * the full extent map from the server, or if the server doesn't
|
|
+ * support base:allocation at all.
|
|
+ */
|
|
+static int
|
|
+extent_callback (void *user_data, const char *metacontext,
|
|
+ uint64_t offset,
|
|
+ uint32_t *entries, size_t nr_entries,
|
|
+ int *error)
|
|
+{
|
|
+ uint32_vector *list = user_data;
|
|
+ size_t i;
|
|
+
|
|
+ if (strcmp (metacontext, LIBNBD_CONTEXT_BASE_ALLOCATION) != 0)
|
|
+ return 0;
|
|
+
|
|
+ /* Just append the entries we got to the list. */
|
|
+ for (i = 0; i < nr_entries; ++i) {
|
|
+ if (uint32_vector_append (list, entries[i]) == -1) {
|
|
+ perror ("realloc");
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static bool
|
|
+test_all_zeroes (uint64_t offset, size_t count)
|
|
+{
|
|
+ uint32_vector entries = empty_vector;
|
|
+ size_t i;
|
|
+ uint64_t count_read;
|
|
+
|
|
+ if (!can_meta_context)
|
|
+ return false;
|
|
+
|
|
+ /* Get the extent map for the block. Note the server doesn't need
|
|
+ * to return all requested data here. If it does not then we return
|
|
+ * false, causing the main code to do a full read. We could be
|
|
+ * smarter and keep asking the server (XXX).
|
|
+ */
|
|
+ if (nbd_block_status (nbd, count, offset,
|
|
+ (nbd_extent_callback) {
|
|
+ .callback = extent_callback,
|
|
+ .user_data = &entries },
|
|
+ 0) == -1) {
|
|
+ fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ count_read = 0;
|
|
+ for (i = 0; i < entries.len; i += 2) {
|
|
+ uint32_t len = entries.ptr[i];
|
|
+ uint32_t type = entries.ptr[i+1];
|
|
+
|
|
+ count_read += len;
|
|
+ if (!(type & 2)) /* not zero */
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /* Did we read at least the whole range wanted? */
|
|
+ if (count_read < count)
|
|
+ return false;
|
|
+
|
|
+ /* If we got here, we read the whole range and it was all zeroes. */
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/* Hexdump the NBD data.
|
|
+ *
|
|
+ * XXX In future we could do this all asynch (including writing to
|
|
+ * stdout) which could make it very efficient.
|
|
+ */
|
|
+static void
|
|
+do_dump (void)
|
|
+{
|
|
+ /* If --no-colour, don't use unicode in the output. */
|
|
+ const char *splat = colour ? "☆" : "*";
|
|
+ const char *pipe = colour ? "│" : "|";
|
|
+ const char *dot = colour ? "·" : ".";
|
|
+ uint64_t offset = 0;
|
|
+ uint64_t count = size > limit ? limit : size;
|
|
+ size_t i, j, n;
|
|
+ char last[16];
|
|
+ bool printed_splat = false, same;
|
|
+
|
|
+ while (count) {
|
|
+ n = MIN (count, sizeof buffer);
|
|
+
|
|
+ if (! test_all_zeroes (offset, n)) {
|
|
+ if (nbd_pread (nbd, buffer, n, offset, 0) == -1) {
|
|
+ fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
|
|
+ exit (EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ memset (buffer, 0, n);
|
|
+ }
|
|
+
|
|
+ /* Make sure a multiple of 16 bytes gets written to the buffer. */
|
|
+ if (n & 15)
|
|
+ memset (&buffer[n], 0, 16 - (n & 15));
|
|
+
|
|
+ for (i = 0; i < n; i += 16) {
|
|
+ /* Is this line the same as the last line? (Squashing) */
|
|
+ same =
|
|
+ offset + i > 0 && /* first line is never squashed */
|
|
+ offset + i + 16 < size && /* last line is never squashed */
|
|
+ memcmp (&buffer[i], last, 16) == 0;
|
|
+ if (same) {
|
|
+ if (!printed_splat) {
|
|
+ printf ("%s\n", splat);
|
|
+ printed_splat = true;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ printed_splat = false;
|
|
+ memcpy (last, &buffer[i], 16); /* Save the current line. */
|
|
+
|
|
+ /* Print the offset. */
|
|
+ ansi_green ();
|
|
+ printf ("%010zx", offset + i);
|
|
+ ansi_grey ();
|
|
+ printf (": ");
|
|
+
|
|
+ /* Print the hex codes. */
|
|
+ for (j = i; j < MIN (i+16, n); ++j) {
|
|
+ if (buffer[j])
|
|
+ ansi_blue ();
|
|
+ else
|
|
+ ansi_grey ();
|
|
+ printf ("%02x ", buffer[j]);
|
|
+ }
|
|
+ ansi_grey ();
|
|
+ for (; j < i+16; ++j)
|
|
+ printf (" ");
|
|
+
|
|
+ /* Print the ASCII codes. */
|
|
+ printf ("%s", pipe);
|
|
+ for (j = i; j < MIN (i+16, n); ++j) {
|
|
+ char c = (char) buffer[j];
|
|
+ if (isalnum (c)) {
|
|
+ ansi_red ();
|
|
+ printf ("%c", c);
|
|
+ }
|
|
+ else if (isprint (c)) {
|
|
+ ansi_magenta ();
|
|
+ printf ("%c", c);
|
|
+ }
|
|
+ else {
|
|
+ ansi_grey ();
|
|
+ printf ("%s", dot);
|
|
+ }
|
|
+ }
|
|
+ ansi_grey ();
|
|
+ for (; j < i+16; ++j)
|
|
+ printf (" ");
|
|
+ printf ("%s\n", pipe);
|
|
+ ansi_restore ();
|
|
+ }
|
|
+
|
|
+ offset += n;
|
|
+ count -= n;
|
|
+ }
|
|
+}
|
|
diff --git a/dump/nbddump.pod b/dump/nbddump.pod
|
|
new file mode 100644
|
|
index 0000000..5d7864d
|
|
--- /dev/null
|
|
+++ b/dump/nbddump.pod
|
|
@@ -0,0 +1,116 @@
|
|
+=head1 NAME
|
|
+
|
|
+nbddump - hexdump the content of a disk over NBD
|
|
+
|
|
+=head1 SYNOPSIS
|
|
+
|
|
+ nbddump NBD
|
|
+
|
|
+C<NBD> is an NBD URI or subprocess:
|
|
+
|
|
+ NBD := nbd://... | nbd+unix:// (or other URI formats)
|
|
+ | [ CMD ARGS ... ]
|
|
+
|
|
+=for paragraph
|
|
+
|
|
+ nbddump --help
|
|
+
|
|
+=for paragraph
|
|
+
|
|
+ nbddump --version
|
|
+
|
|
+=head1 DESCRIPTION
|
|
+
|
|
+nbddump prints the content of a disk from an NBD server using the
|
|
+usual hexdump format:
|
|
+
|
|
+ $ nbddump nbd://localhost
|
|
+ 0000: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │················│
|
|
+ 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │················│
|
|
+ ☆
|
|
+ 0100: 68 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 00 00 00 │hello, world!···│
|
|
+ 0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │················│
|
|
+ ☆
|
|
+ 1000: 00 00 00 21 │···! │
|
|
+
|
|
+=head2 Output format
|
|
+
|
|
+The first field (before the C<:>) is the offset within the file, in
|
|
+hexadecimal.
|
|
+
|
|
+The second field shows the hex codes of bytes read from the file.
|
|
+
|
|
+The third field shows the ASCII equivalent characters (if printable).
|
|
+
|
|
+A splat character (C<☆>) indicates lines of repeated output which have
|
|
+been squashed. (Note this is not just for lines of zero bytes, but
|
|
+any case where the next line shown would be the same as the previous
|
|
+line.)
|
|
+
|
|
+=head2 Subprocess
|
|
+
|
|
+nbddump can also run an NBD server as a subprocess. This requires an
|
|
+NBD server which understands systemd socket activation, such as
|
|
+L<qemu-nbd(8)> or L<nbdkit(1)>.
|
|
+
|
|
+For example, to dump out a qcow2 file as raw data:
|
|
+
|
|
+ nbddump -- [ qemu-nbd -r -f qcow2 file.qcow2 ]
|
|
+
|
|
+Note that S<C<[ ... ]>> are separate parameters, and must be
|
|
+surrounded by spaces. C<--> separates nbddump parameters from
|
|
+subprocess parameters.
|
|
+
|
|
+=head1 OPTIONS
|
|
+
|
|
+=over 4
|
|
+
|
|
+=item B<--help>
|
|
+
|
|
+Display brief command line help and exit.
|
|
+
|
|
+=item B<--color>
|
|
+
|
|
+=item B<--colour>
|
|
+
|
|
+=item B<--no-color>
|
|
+
|
|
+=item B<--no-colour>
|
|
+
|
|
+Enable or disable ANSI colours in output. By default we use colours
|
|
+if the output seems to be a terminal, and disable them if not.
|
|
+
|
|
+=item B<--length=>N
|
|
+
|
|
+=item B<-n> N
|
|
+
|
|
+Dump up to I<N> bytes and then stop.
|
|
+
|
|
+=item B<-V>
|
|
+
|
|
+=item B<--version>
|
|
+
|
|
+Display the package name and version and exit.
|
|
+
|
|
+=back
|
|
+
|
|
+=head1 SEE ALSO
|
|
+
|
|
+L<libnbd(3)>,
|
|
+L<nbdcopy(1)>,
|
|
+L<nbdfuse(1)>,
|
|
+L<nbdinfo(1)>,
|
|
+L<nbdsh(1)>,
|
|
+L<hexdump(1)>,
|
|
+L<file(1)>,
|
|
+L<qemu-img(1)>,
|
|
+L<nbdkit(1)>,
|
|
+L<qemu-nbd(8)>.
|
|
+
|
|
+=head1 AUTHORS
|
|
+
|
|
+Richard W.M. Jones
|
|
+
|
|
+=head1 COPYRIGHT
|
|
+
|
|
+Copyright (C) 2022 Red Hat Inc.
|
|
diff --git a/dump/test-long-options.sh b/dump/test-long-options.sh
|
|
new file mode 100755
|
|
index 0000000..924c8f5
|
|
--- /dev/null
|
|
+++ b/dump/test-long-options.sh
|
|
@@ -0,0 +1,35 @@
|
|
+#!/usr/bin/env bash
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2019-2022 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 nbddump --long-options looks sane.
|
|
+
|
|
+. ../tests/functions.sh
|
|
+set -e
|
|
+set -x
|
|
+
|
|
+output=test-long-options.out
|
|
+cleanup_fn rm -f $output
|
|
+
|
|
+$VG nbddump --long-options > $output
|
|
+if [ $? != 0 ]; then
|
|
+ echo "$0: unexpected exit status"
|
|
+ fail=1
|
|
+fi
|
|
+cat $output
|
|
+grep -- --length $output
|
|
+grep -- --version $output
|
|
diff --git a/dump/test-short-options.sh b/dump/test-short-options.sh
|
|
new file mode 100755
|
|
index 0000000..325f7df
|
|
--- /dev/null
|
|
+++ b/dump/test-short-options.sh
|
|
@@ -0,0 +1,35 @@
|
|
+#!/usr/bin/env bash
|
|
+# nbd client library in userspace
|
|
+# Copyright (C) 2019-2022 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 nbddump --short-options looks sane.
|
|
+
|
|
+. ../tests/functions.sh
|
|
+set -e
|
|
+set -x
|
|
+
|
|
+output=test-short-options.out
|
|
+cleanup_fn rm -f $output
|
|
+
|
|
+$VG nbddump --short-options > $output
|
|
+if [ $? != 0 ]; then
|
|
+ echo "$0: unexpected exit status"
|
|
+ fail=1
|
|
+fi
|
|
+cat $output
|
|
+grep -- -n $output
|
|
+grep -- -V $output
|
|
diff --git a/dump/test-version.sh b/dump/test-version.sh
|
|
new file mode 100755
|
|
index 0000000..fce4ed1
|
|
--- /dev/null
|
|
+++ b/dump/test-version.sh
|
|
@@ -0,0 +1,33 @@
|
|
+#!/usr/bin/env bash
|
|
+# 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
|
|
+
|
|
+# Test that nbddump --version looks sane.
|
|
+
|
|
+fail=0
|
|
+output=$($VG nbddump --version)
|
|
+if [ $? != 0 ]; then
|
|
+ echo "$0: unexpected exit status"
|
|
+ fail=1
|
|
+fi
|
|
+if [ "$output" != "nbddump $EXPECTED_VERSION
|
|
+libnbd $EXPECTED_VERSION" ]; then
|
|
+ echo "$0: unexpected output"
|
|
+ fail=1
|
|
+fi
|
|
+echo "$output"
|
|
+exit $fail
|
|
diff --git a/fuse/nbdfuse.pod b/fuse/nbdfuse.pod
|
|
index 7c1c817..daa79c1 100644
|
|
--- a/fuse/nbdfuse.pod
|
|
+++ b/fuse/nbdfuse.pod
|
|
@@ -412,6 +412,7 @@ The differences from nbdfuse are similar to the list above.
|
|
|
|
L<libnbd(3)>,
|
|
L<nbdcopy(1)>,
|
|
+L<nbddump(1)>,
|
|
L<nbdinfo(1)>,
|
|
L<nbdsh(1)>,
|
|
L<fusermount3(1)>,
|
|
diff --git a/info/nbdinfo.pod b/info/nbdinfo.pod
|
|
index 649cf1c..4733ecd 100644
|
|
--- a/info/nbdinfo.pod
|
|
+++ b/info/nbdinfo.pod
|
|
@@ -407,6 +407,7 @@ Display the package name and version and exit.
|
|
|
|
L<libnbd(3)>,
|
|
L<nbdcopy(1)>,
|
|
+L<nbddump(1)>,
|
|
L<nbdfuse(1)>,
|
|
L<nbdsh(1)>,
|
|
L<file(1)>,
|
|
diff --git a/run.in b/run.in
|
|
index 8a21906..2a171e5 100755
|
|
--- a/run.in
|
|
+++ b/run.in
|
|
@@ -58,6 +58,7 @@ b="$(cd @abs_builddir@ && pwd)"
|
|
|
|
# Set the PATH to contain all libnbd binaries.
|
|
prepend PATH "$b/copy"
|
|
+prepend PATH "$b/dump"
|
|
prepend PATH "$b/fuse"
|
|
prepend PATH "$b/info"
|
|
prepend PATH "$b/sh"
|
|
diff --git a/sh/nbdsh.pod b/sh/nbdsh.pod
|
|
index ca5d6af..c9dac4a 100644
|
|
--- a/sh/nbdsh.pod
|
|
+++ b/sh/nbdsh.pod
|
|
@@ -147,6 +147,7 @@ L<https://gitlab.com/nbdkit/libnbd/tree/master/python/examples>.
|
|
L<libnbd(3)>,
|
|
L<libnbd-security(3)>,
|
|
L<nbdcopy(1)>,
|
|
+L<nbddump(1)>,
|
|
L<nbdfuse(1)>,
|
|
L<nbdinfo(1)>,
|
|
L<qemu-img(1)>.
|
|
--
|
|
2.31.1
|
|
|