Richard W.M. Jones
2018-Jun-07 15:48 UTC
[Libguestfs] [PATCH nbdkit 0/4] plugins: Add new "ext2" plugin, for accessing ext2, ext3 or ext4 filesystems.
There is a small test provided. I tested this a lot more locally and it seems pretty robust. Rich.
Richard W.M. Jones
2018-Jun-07 15:48 UTC
[Libguestfs] [PATCH nbdkit 1/4] plugins: guestfs: This plugin is only safe when serializing connections.
If two connections are both made at the same time then they would both open a guestfs handle, possible for write, on the same set of disks. With older qemu this would result in disk corruption, with newer qemu you'd get just a locking failure. --- plugins/guestfs/guestfs-plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/guestfs/guestfs-plugin.c b/plugins/guestfs/guestfs-plugin.c index 66788d8..1572940 100644 --- a/plugins/guestfs/guestfs-plugin.c +++ b/plugins/guestfs/guestfs-plugin.c @@ -492,7 +492,7 @@ plugin_guestfs_close (void *handle) free (h); } -#define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS +#define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS /* Get the file size. */ static int64_t -- 2.16.2
Richard W.M. Jones
2018-Jun-07 15:48 UTC
[Libguestfs] [PATCH nbdkit 2/4] tests: Move creation of ‘disk’ earlier.
Just refactoring. --- tests/Makefile.am | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 0cc2618..1830cd3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -232,6 +232,18 @@ test_oldstyle_LDADD = libtest.la $(LIBGUESTFS_LIBS) endif HAVE_LIBGUESTFS +# common disk image shared with several tests +if HAVE_GUESTFISH +check_DATA += disk +MAINTAINERCLEANFILES += disk + +disk: + rm -f $@ test1.img + guestfish -N fs -m /dev/sda1 write /hello.txt "hello,world" + mv test1.img disk + +endif HAVE_GUESTFISH + # file plugin test. LIBGUESTFS_TESTS += test-file @@ -241,26 +253,19 @@ test_file_LDADD = libtest.la $(LIBGUESTFS_LIBS) # gzip plugin test. if HAVE_ZLIB -if HAVE_GUESTFISH LIBGUESTFS_TESTS += test-gzip -check_DATA += disk disk.gz -MAINTAINERCLEANFILES += disk disk.gz +check_DATA += disk.gz +MAINTAINERCLEANFILES += disk.gz test_gzip_SOURCES = test-gzip.c test.h test_gzip_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS) test_gzip_LDADD = libtest.la $(LIBGUESTFS_LIBS) -disk: - rm -f $@ test1.img - guestfish -N fs -m /dev/sda1 write /hello.txt "hello,world" - mv test1.img disk - disk.gz: disk rm -f $@ gzip -9 -c disk > $@ -endif HAVE_GUESTFISH endif HAVE_ZLIB # memory plugin test. @@ -316,7 +321,6 @@ test_streaming_LDADD = libtest.la $(LIBGUESTFS_LIBS) # xz plugin test. if HAVE_LIBLZMA -if HAVE_GUESTFISH LIBGUESTFS_TESTS += test-xz check_DATA += disk.xz @@ -330,7 +334,6 @@ disk.xz: disk rm -f $@ xz --best --block-size=16777216 -c disk > $@ -endif HAVE_GUESTFISH endif HAVE_LIBLZMA #---------------------------------------------------------------------- -- 2.16.2
Richard W.M. Jones
2018-Jun-07 15:48 UTC
[Libguestfs] [PATCH nbdkit 3/4] plugins: Add new "ext2" plugin, for accessing ext2, ext3 or ext4 filesystems.
---
README | 6 +
configure.ac | 24 +++
docs/nbdkit.pod | 1 +
plugins/Makefile.am | 1 +
plugins/ext2/Makefile.am | 68 +++++++
plugins/ext2/ext2.c | 359 ++++++++++++++++++++++++++++++++++++
plugins/ext2/nbdkit-ext2-plugin.pod | 130 +++++++++++++
7 files changed, 589 insertions(+)
diff --git a/README b/README
index baa29fc..e58df8b 100644
--- a/README
+++ b/README
@@ -65,6 +65,12 @@ For the libguestfs plugin, and to run the test suite:
- guestfish (from libguestfs)
+For the ext2 plugin:
+
+ - ext2fs
+
+ - com_err
+
For the VDDK plugin:
- VDDK (see plugins/vddk/README.VDDK)
diff --git a/configure.ac b/configure.ac
index 4bd9aac..c86c6ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,6 +426,29 @@ dnl Check for guestfish (only needed for some of the
tests).
AC_CHECK_PROG([GUESTFISH], [guestfish], [guestfish], [no])
AM_CONDITIONAL([HAVE_GUESTFISH], [test "x$GUESTFISH" !=
"xno"])
+dnl Check for ext2fs and com_err, for the ext2 plugin.
+AC_ARG_WITH([ext2],[
+ AS_HELP_STRING([--without-ext2],
+ [disable ext2 plugin @<:@default=check@:>@])],
+ [],
+ [with_ext2=check])
+AS_IF([test "$with_ext2" != "no"], [
+ PKG_CHECK_MODULES([EXT2FS], [ext2fs], [
+ AC_SUBST([EXT2FS_CFLAGS])
+ AC_SUBST([EXT2FS_LIBS])
+ AC_DEFINE([HAVE_EXT2FS],[1],[ext2fs found at compile time.])
+ ],
+ [AC_MSG_WARN([ext2fs not found, ext2 plugin will be disabled])])
+ PKG_CHECK_MODULES([COM_ERR], [com_err], [
+ AC_SUBST([COM_ERR_CFLAGS])
+ AC_SUBST([COM_ERR_LIBS])
+ AC_DEFINE([HAVE_COM_ERR],[1],[com_err found at compile time.])
+ ],
+ [AC_MSG_WARN([com_err not found, ext2 plugin will be disabled])])
+])
+AM_CONDITIONAL([HAVE_EXT2],
+ [test "x$EXT2FS_LIBS" != "x" && test
"x$COM_ERR_LIBS" != "x"])
+
dnl See plugins/vddk/README.VDDK.
AC_CHECK_SIZEOF([size_t])
AS_IF([test "x$ac_cv_sizeof_size_t" =
"x4"],[bits=32],[bits=64])
@@ -511,6 +534,7 @@ AC_CONFIG_FILES([Makefile
plugins/example2/Makefile
plugins/example3/Makefile
plugins/example4/Makefile
+ plugins/ext2/Makefile
plugins/file/Makefile
plugins/guestfs/Makefile
plugins/gzip/Makefile
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index a515353..6ba981b 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -909,6 +909,7 @@ L<nbdkit-example1-plugin(1)>,
L<nbdkit-example2-plugin(1)>,
L<nbdkit-example3-plugin(1)>,
L<nbdkit-example4-plugin(1)>,
+L<nbdkit-ext2-plugin(1)>,
L<nbdkit-file-plugin(1)>,
L<nbdkit-guestfs-plugin(1)>,
L<nbdkit-gzip-plugin(1)>,
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index ba67feb..328bc01 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -36,6 +36,7 @@ SUBDIRS = \
example2 \
example3 \
example4 \
+ ext2 \
file \
guestfs \
gzip \
diff --git a/plugins/ext2/Makefile.am b/plugins/ext2/Makefile.am
new file mode 100644
index 0000000..525013f
--- /dev/null
+++ b/plugins/ext2/Makefile.am
@@ -0,0 +1,68 @@
+# nbdkit
+# Copyright (C) 2017-2018 Red Hat Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+EXTRA_DIST = nbdkit-ext2-plugin.pod
+
+CLEANFILES = *~
+
+plugindir = $(libdir)/nbdkit/plugins
+
+if HAVE_EXT2
+
+plugin_LTLIBRARIES = nbdkit-ext2-plugin.la
+
+nbdkit_ext2_plugin_la_SOURCES = \
+ ext2.c \
+ $(top_srcdir)/include/nbdkit-plugin.h
+
+nbdkit_ext2_plugin_la_CPPFLAGS = \
+ -I$(top_srcdir)/include
+nbdkit_ext2_plugin_la_CFLAGS = \
+ $(WARNINGS_CFLAGS) \
+ $(EXT2FS_CFLAGS) $(COM_ERR_CFLAGS)
+nbdkit_ext2_plugin_la_LIBADD = \
+ $(EXT2FS_LIBS) $(COM_ERR_LIBS)
+nbdkit_ext2_plugin_la_LDFLAGS = \
+ -module -avoid-version -shared
+
+if HAVE_POD2MAN
+
+man_MANS = nbdkit-ext2-plugin.1
+CLEANFILES += $(man_MANS)
+
+nbdkit-ext2-plugin.1: nbdkit-ext2-plugin.pod
+ $(POD2MAN) $(POD2MAN_ARGS) --section=1 --name=`basename $@ .1` $< $@.t
&& \
+ if grep 'POD ERROR' $@.t; then rm $@.t; exit 1; fi && \
+ mv $@.t $@
+
+endif
+endif
diff --git a/plugins/ext2/ext2.c b/plugins/ext2/ext2.c
new file mode 100644
index 0000000..1e8f6dd
--- /dev/null
+++ b/plugins/ext2/ext2.c
@@ -0,0 +1,359 @@
+/* nbdkit
+ * Copyright (C) 2017-2018 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+/* Inlining is broken in the ext2fs header file. Disable it by
+ * defining the following:
+ */
+#define NO_INLINE_FUNCS
+#include <ext2fs.h>
+
+#define NBDKIT_API_VERSION 2
+
+#include <nbdkit-plugin.h>
+
+/* Disk image and filename parameters. */
+static char *disk;
+static char *file;
+
+static void
+ext2_load (void)
+{
+ initialize_ext2_error_table ();
+}
+
+static void
+ext2_unload (void)
+{
+ free (disk);
+ free (file);
+}
+
+static int
+ext2_config (const char *key, const char *value)
+{
+ if (strcmp (key, "disk") == 0) {
+ if (disk != NULL) {
+ nbdkit_error ("disk parameter specified more than once");
+ return -1;
+ }
+ disk = nbdkit_absolute_path (value);
+ if (disk == NULL)
+ return -1;
+ }
+ else if (strcmp (key, "file") == 0) {
+ if (file != NULL) {
+ nbdkit_error ("file parameter specified more than once");
+ return -1;
+ }
+ file = strdup (value);
+ if (file == NULL) {
+ nbdkit_error ("strdup: %m");
+ return -1;
+ }
+ }
+ else {
+ nbdkit_error ("unknown parameter '%s'", key);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+ext2_config_complete (void)
+{
+ if (disk == NULL || file == NULL) {
+ nbdkit_error ("you must supply disk=<DISK> and file=<FILE>
parameters "
+ "after the plugin name on the command line");
+ return -1;
+ }
+
+ if (file[0] != '/') {
+ nbdkit_error ("the file parameter must refer to an absolute
path");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define ext2_config_help \
+ "disk=<FILENAME> (required) Raw ext2, ext3 or ext4
filesystem.\n" \
+ "file=<FILENAME> (required) File to serve inside the disk
image."
+
+/* The per-connection handle. */
+struct handle {
+ int readonly;
+ ext2_filsys fs; /* Filesystem handle. */
+ ext2_ino_t ino; /* Inode of open file. */
+ ext2_file_t file; /* File handle. */
+};
+
+/* Create the per-connection handle. */
+static void *
+ext2_open (int readonly)
+{
+ struct handle *h;
+ errcode_t err;
+ int fs_flags;
+ int file_flags;
+ struct ext2_inode inode;
+
+ h = malloc (sizeof *h);
+ if (h == NULL) {
+ nbdkit_error ("malloc: %m");
+ return NULL;
+ }
+
+ h->readonly = readonly;
+
+ fs_flags = 0;
+#ifdef EXT2_FLAG_64BITS
+ fs_flags |= EXT2_FLAG_64BITS;
+#endif
+ if (!readonly)
+ fs_flags |= EXT2_FLAG_RW;
+
+ err = ext2fs_open (disk, fs_flags, 0, 0, unix_io_manager, &h->fs);
+ if (err != 0) {
+ nbdkit_error ("%s: open: %s", disk, error_message (err));
+ goto err0;
+ }
+
+ if (strcmp (file, "/") == 0)
+ /* probably gonna fail, but we'll catch it later */
+ h->ino = EXT2_ROOT_INO;
+ else {
+ err = ext2fs_namei (h->fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+ &file[1], &h->ino);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: namei: %s", disk, file, error_message
(err));
+ goto err1;
+ }
+ }
+
+ /* Check the file is a regular file.
+ * XXX This won't follow symlinks, we'd have to do that manually.
+ */
+ err = ext2fs_read_inode (h->fs, h->ino, &inode);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: inode: %s", disk, file, error_message
(err));
+ goto err1;
+ }
+ if (!LINUX_S_ISREG (inode.i_mode)) {
+ nbdkit_error ("%s: %s: must be a regular file in the disk image",
+ disk, file);
+ goto err1;
+ }
+
+ file_flags = 0;
+ if (!readonly)
+ file_flags |= EXT2_FILE_WRITE;
+ err = ext2fs_file_open2 (h->fs, h->ino, NULL, file_flags,
&h->file);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: open: %s", disk, file, error_message
(err));
+ goto err1;
+ }
+
+ return h;
+
+ err1:
+ ext2fs_close (h->fs);
+ err0:
+ free (h);
+ return NULL;
+}
+
+/* Free up the per-connection handle. */
+static void
+ext2_close (void *handle)
+{
+ struct handle *h = handle;
+
+ ext2fs_file_close (h->file);
+ ext2fs_close (h->fs);
+ free (h);
+}
+
+static int
+ext2_can_fua (void *handle)
+{
+ return NBDKIT_FUA_NATIVE;
+}
+
+/* It might be possible to relax this, but it's complicated.
+ *
+ * It's desirable for ‘nbdkit -r’ to behave the same way as
+ * ‘mount -o ro’. But we don't know the state of the readonly flag
+ * until ext2_open is called (because the NBD client can also request
+ * a readonly connection). So we could not set the "ro" flag if we
+ * opened the filesystem any earlier (eg in ext2_config).
+ *
+ * So out of necessity we have one ext2_filsys handle per connection,
+ * but if we allowed parallel work on those handles then we would get
+ * data corruption, so we need to serialize connections.
+ */
+#define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS
+
+/* Get the disk size. */
+static int64_t
+ext2_get_size (void *handle)
+{
+ struct handle *h = handle;
+ errcode_t err;
+ uint64_t size;
+
+ err = ext2fs_file_get_lsize (h->file, (__u64 *) &size);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: lsize: %s", disk, file, error_message
(err));
+ return -1;
+ }
+ return (int64_t) size;
+}
+
+/* Read data. */
+static int
+ext2_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ struct handle *h = handle;
+ errcode_t err;
+ unsigned int got;
+
+ while (count > 0) {
+ /* Although this function weirdly can return the new offset,
+ * examination of the code shows that it never returns anything
+ * different from what we set, so NULL out that parameter.
+ */
+ err = ext2fs_file_llseek (h->file, offset, EXT2_SEEK_SET, NULL);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: llseek: %s", disk, file, error_message
(err));
+ return -1;
+ }
+
+ err = ext2fs_file_read (h->file, buf, (unsigned int) count, &got);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: read: %s", disk, file, error_message
(err));
+ return -1;
+ }
+
+ buf += got;
+ count -= got;
+ offset += got;
+ }
+
+ return 0;
+}
+
+/* Write data to the file. */
+static int
+ext2_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ struct handle *h = handle;
+ errcode_t err;
+ unsigned int written;
+
+ while (count > 0) {
+ err = ext2fs_file_llseek (h->file, offset, EXT2_SEEK_SET, NULL);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: llseek: %s", disk, file, error_message
(err));
+ return -1;
+ }
+
+ err = ext2fs_file_write (h->file, buf, (unsigned int) count,
&written);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: write: %s", disk, file, error_message
(err));
+ return -1;
+ }
+
+ buf += written;
+ count -= written;
+ offset += written;
+ }
+
+ if ((flags & NBDKIT_FLAG_FUA) != 0) {
+ err = ext2fs_file_flush (h->file);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: flush: %s", disk, file, error_message
(err));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+ext2_flush (void *handle, uint32_t flags)
+{
+ struct handle *h = handle;
+ errcode_t err;
+
+ err = ext2fs_file_flush (h->file);
+ if (err != 0) {
+ nbdkit_error ("%s: %s: flush: %s", disk, file, error_message
(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* XXX It seems as if we should be able to support trim and zero, if
+ * we could work out how those are implemented in the ext2fs API which
+ * is very obscure.
+ */
+
+static struct nbdkit_plugin plugin = {
+ .name = "ext2",
+ .version = PACKAGE_VERSION,
+ .load = ext2_load,
+ .unload = ext2_unload,
+ .config = ext2_config,
+ .config_complete = ext2_config_complete,
+ .config_help = ext2_config_help,
+ .open = ext2_open,
+ .close = ext2_close,
+ .can_fua = ext2_can_fua,
+ .get_size = ext2_get_size,
+ .pread = ext2_pread,
+ .pwrite = ext2_pwrite,
+ .flush = ext2_flush,
+ .errno_is_preserved = 1,
+};
+
+NBDKIT_REGISTER_PLUGIN(plugin)
diff --git a/plugins/ext2/nbdkit-ext2-plugin.pod
b/plugins/ext2/nbdkit-ext2-plugin.pod
new file mode 100644
index 0000000..29c76aa
--- /dev/null
+++ b/plugins/ext2/nbdkit-ext2-plugin.pod
@@ -0,0 +1,130 @@
+=encoding utf8
+
+=head1 NAME
+
+nbdkit-ext2-plugin - Read and write files inside ext2, ext3 or ext4 filesystems
+
+=head1 SYNOPSIS
+
+ nbdkit ext2 disk=fs.img file=/disks/disk.raw
+
+ nbdkit --filter=partition ext2 \
+ disk=disk.img file=/disks/disk.raw \
+ partition=1
+
+=head1 DESCRIPTION
+
+C<nbdkit-ext2-plugin> is an nbdkit plugin which can read and
+write files inside ext2, ext3 or ext4 filesystem images.
+
+Suppose you have an ext2/3/4 filesystem image called F<fs.img>
+which contains inside itself a file called F<disk.raw>
+inside a directory on the filesystem called F</disks>, then
+you could serve that file over NBD using:
+
+ nbdkit ext2 disk=fs.img file=/disks/disk.raw
+
+Commonly disk images are partitioned. In that case you must
+use L<nbdkit-partition-filter(1)> to select the partition:
+
+ nbdkit --filter=partition ext2 disk=.. file=.. partition=1
+
+This plugin can both read and write to the file inside the filesystem.
+Use the I<-r> flag to force a readonly connection, but note this does
+I<not> guarantee that no writes are made to the filesystem. In
+particular we may have to replay the ext3 journal in order to open a
+filesystem even read-only.
+
+The plugin does I<not> support multiple parallel connections, because
+there is a risk of corrupting the filesystem (as if the filesystem was
+mounted by multiple machines). If a second connection is made to
+nbdkit, it will block until the first connection closes.
+
+The plugin is implemented using the ext2fs library which is provided
+in most Linux distros, and also available as part of the e2fsprogs
+project.
+
+L<nbdkit-guestfs-plugin(1)> is a more generic plugin which can read
+files from all kinds of different filesystem types, even if they are
+partitioned or use logical volumes. It uses libguestfs instead of
+e2fsprogs.
+
+=head1 PARAMETERS
+
+=over 4
+
+=item B<disk=FILENAME>
+
+The ext2, ext3 or ext4 filesystem, a file on the host.
+
+You could also use a device name here if the filesystem is located on
+a device. Be careful that the filesystem is not being accessed in
+parallel by another program and is not mounted, as that will almost
+certainly result in disk corruption in the filesystem.
+
+The plugin expects a raw filesystem. If the file/device is
+partitioned, use L<nbdkit-partition-filter(1)>.
+
+=item B<file=PATH>
+
+The full path of the file within the filesystem that will be exposed
+over NBD. The path must be absolute (starts with C</>).
+
+=back
+
+=head1 SEE ALSO
+
+L<nbdkit(1)>,
+L<nbdkit-plugin(3)>,
+L<nbdkit-partition-filter(1)>,
+L<nbdkit-guestfs-plugin(1)>,
+L<http://e2fsprogs.sourceforge.net/>,
+L<fuse2fs(1)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones
+
+=head1 COPYRIGHT
+
+Copyright (C) 2018 Red Hat Inc.
+
+=head1 LICENSE
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+=over 4
+
+=item *
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+=item *
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+=item *
+
+Neither the name of Red Hat nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+=back
+
+THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS''
AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
--
2.16.2
Richard W.M. Jones
2018-Jun-07 15:48 UTC
[Libguestfs] [PATCH nbdkit 4/4] tests: Add test of the ext2 plugin.
---
.gitignore | 2 ++
tests/Makefile.am | 26 ++++++++++++++++
tests/test-ext2.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 120 insertions(+)
diff --git a/.gitignore b/.gitignore
index 3b7365f..f41de87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,7 @@ Makefile.in
/tests/disk
/tests/disk.gz
/tests/disk.xz
+/tests/ext2.img
/tests/file-data
/tests/offset-data
/tests/partition-disk
@@ -57,6 +58,7 @@ Makefile.in
/tests/test-connect
/tests/test-delay
/tests/test-exit-with-parent
+/tests/test-ext2
/tests/test-file
/tests/test-gzip
/tests/test-memory
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1830cd3..850240b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -244,6 +244,32 @@ disk:
endif HAVE_GUESTFISH
+# ext2 plugin test.
+if HAVE_EXT2
+if HAVE_GUESTFISH
+
+LIBGUESTFS_TESTS += test-ext2
+check_DATA += ext2.img
+MAINTAINERCLEANFILES += ext2.img
+
+ext2.img: disk
+ rm -f $@ $@-t
+ guestfish \
+ sparse $@-t 2G : \
+ run : \
+ mkfs ext4 /dev/sda : \
+ mount /dev/sda / : \
+ mkdir /disks : \
+ upload $< /disks/disk.img
+ mv $@-t $@
+
+test_ext2_SOURCES = test-ext2.c test.h
+test_ext2_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
+test_ext2_LDADD = libtest.la $(LIBGUESTFS_LIBS)
+
+endif HAVE_GUESTFISH
+endif HAVE_EXT2
+
# file plugin test.
LIBGUESTFS_TESTS += test-file
diff --git a/tests/test-ext2.c b/tests/test-ext2.c
new file mode 100644
index 0000000..b222533
--- /dev/null
+++ b/tests/test-ext2.c
@@ -0,0 +1,92 @@
+/* nbdkit
+ * Copyright (C) 2013-2018 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <guestfs.h>
+
+#include "test.h"
+
+int
+main (int argc, char *argv[])
+{
+ guestfs_h *g;
+ int r;
+ char *data;
+
+ if (test_start_nbdkit ("ext2", "-r",
"disk=ext2.img", "file=/disks/disk.img",
+ NULL) == -1)
+ exit (EXIT_FAILURE);
+
+ g = guestfs_create ();
+ if (g == NULL) {
+ perror ("guestfs_create");
+ exit (EXIT_FAILURE);
+ }
+
+ r = guestfs_add_drive_opts (g, "",
+ GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
+ GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
+ GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
+ -1);
+ if (r == -1)
+ exit (EXIT_FAILURE);
+
+ if (guestfs_launch (g) == -1)
+ exit (EXIT_FAILURE);
+
+ /* disk.img contains one partition and a test file called
"hello.txt" */
+ if (guestfs_mount_ro (g, "/dev/sda1", "/") == -1)
+ exit (EXIT_FAILURE);
+
+ data = guestfs_cat (g, "/hello.txt");
+ if (!data)
+ exit (EXIT_FAILURE);
+
+ if (strcmp (data, "hello,world") != 0) {
+ fprintf (stderr, "%s FAILED: unexpected content of /hello.txt file
(actual: %s, expected: \"hello,world\")\n",
+ program_name, data);
+ exit (EXIT_FAILURE);
+ }
+
+ guestfs_close (g);
+ exit (EXIT_SUCCESS);
+}
--
2.16.2