[PATCH 1/7] mount: Add mount_vfs_nochroot This is significantly reworked from before. umount is gone as discussed, and variable motion is minimised. [PATCH 2/7] btrfs: Update btrfs_subvolume_list to take Already provisionally ACKed. Previous comment was that cleanup could be tidier. I looked into creating a new cleanup function for fs_buf, but it isn't possible (or simple, anyway) in this case for 2 reasons: 1. You'd need 2 arguments passed to the cleanup function, not one. Without fs->type you don't know whether fs_buf has been mounted or not. 2. You can't catch and report an error. [PATCH 3/7] mountable: Make list-filesystems return btrfsvols Already provisionally ACKed. [PATCH 4/7] New internal API: internal_parse_mountable [PATCH 5/7] inspect: Update inspect_os to use mountables [PATCH 6/7] btrfs: Make a stub Fedora btrfs guest for inspection [PATCH 7/7] mountable: Test inspection of fedora image Not previously reviewed.
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 1/7] mount: Add mount_vfs_nochroot
This internal function allows mounting a mountable outside /sysroot.
---
daemon/daemon.h | 6 ++++++
daemon/mount.c | 14 +++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 67adec0..d343dfd 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -65,6 +65,12 @@ extern int xread (int sock, void *buf, size_t len)
extern char *mountable_to_string (const mountable_t *mountable);
+/*-- in mount.c --*/
+
+extern int mount_vfs_nochroot (const char *options, const char *vfstype,
+ const mountable_t *mountable,
+ const char *mp, const char *user_mp);
+
/* Growable strings buffer. */
struct stringsbuf {
char **argv;
diff --git a/daemon/mount.c b/daemon/mount.c
index 7e1199f..452b938 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -126,9 +126,7 @@ int
do_mount_vfs (const char *options, const char *vfstype,
const mountable_t *mountable, const char *mountpoint)
{
- int r;
CLEANUP_FREE char *mp = NULL;
- CLEANUP_FREE char *error = NULL;
struct stat statbuf;
ABS_PATH (mountpoint, , return -1);
@@ -149,6 +147,14 @@ do_mount_vfs (const char *options, const char *vfstype,
return -1;
}
+ return mount_vfs_nochroot (options, vfstype, mountable, mp, mountpoint);
+}
+
+int
+mount_vfs_nochroot (const char *options, const char *vfstype,
+ const mountable_t *mountable,
+ const char *mp, const char *user_mp)
+{
CLEANUP_FREE char *options_plus = NULL;
const char *device = mountable->device;
if (mountable->type == MOUNTABLE_BTRFSVOL) {
@@ -169,6 +175,8 @@ do_mount_vfs (const char *options, const char *vfstype,
}
}
+ CLEANUP_FREE char *error = NULL;
+ int r;
if (vfstype)
r = command (NULL, &error,
str_mount, "-o", options_plus ? options_plus :
options,
@@ -179,7 +187,7 @@ do_mount_vfs (const char *options, const char *vfstype,
device, mp, NULL);
if (r == -1) {
reply_with_error ("%s on %s (options: '%s'): %s",
- device, mountpoint, options, error);
+ device, user_mp, options, error);
return -1;
}
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 2/7] btrfs: Update btrfs_subvolume_list to take Mountable_or_Path
btrfs_subvolume_list can now take either the path of a mounted btrfs
filesystem, or a mountable describing the location of a btrfs
filesystem, or one of its volumes. In the latter case, the filesystem
will be automatically mounted outside of /sysroot before running the
btrfs tool, and unmounted afterwards.
---
daemon/btrfs.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--------
generator/actions.ml | 2 +-
2 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index 81ce5f5..c3247ac 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -34,6 +34,7 @@ GUESTFSD_EXT_CMD(str_btrfs, btrfs);
GUESTFSD_EXT_CMD(str_btrfstune, btrfstune);
GUESTFSD_EXT_CMD(str_btrfsck, btrfsck);
GUESTFSD_EXT_CMD(str_mkfs_btrfs, mkfs.btrfs);
+GUESTFSD_EXT_CMD(str_umount, umount);
int
optgroup_btrfs_available (void)
@@ -307,16 +308,47 @@ do_btrfs_subvolume_create (const char *dest)
}
guestfs_int_btrfssubvolume_list *
-do_btrfs_subvolume_list (const char *fs)
+do_btrfs_subvolume_list (const mountable_t *fs)
{
char **lines;
/* Execute 'btrfs subvolume list <fs>', and split the output
into lines */
{
- CLEANUP_FREE char *fs_buf = sysroot_path (fs);
- if (fs_buf == NULL) {
- reply_with_perror ("malloc");
- return NULL;
+ CLEANUP_FREE char *fs_buf = NULL;
+
+ if (fs->type == MOUNTABLE_PATH) {
+ fs_buf = sysroot_path (fs->device);
+ if (fs_buf == NULL) {
+ reply_with_perror ("malloc");
+
+ cmderror:
+ if (fs->type != MOUNTABLE_PATH && fs_buf) {
+ CLEANUP_FREE char *err = NULL;
+ if (command (NULL, &err, str_umount, fs_buf, NULL) == -1)
+ fprintf (stderr, "%s\n", err);
+
+ if (rmdir (fs_buf) == -1 && errno != ENOENT)
+ fprintf (stderr, "rmdir: %m\n");
+ }
+ return NULL;
+ }
+ }
+
+ else {
+ fs_buf = strdup ("/tmp/btrfs.XXXXXX");
+ if (fs_buf == NULL) {
+ reply_with_perror ("strdup");
+ goto cmderror;
+ }
+
+ if (mkdtemp (fs_buf) == NULL) {
+ reply_with_perror ("mkdtemp");
+ goto cmderror;
+ }
+
+ if (mount_vfs_nochroot ("", NULL, fs, fs_buf,
"<internal>") == -1) {
+ goto cmderror;
+ }
}
size_t i = 0;
@@ -328,16 +360,33 @@ do_btrfs_subvolume_list (const char *fs)
ADD_ARG (argv, i, fs_buf);
ADD_ARG (argv, i, NULL);
- CLEANUP_FREE char *out = NULL, *err = NULL;
- int r = commandv (&out, &err, argv);
+ CLEANUP_FREE char *out = NULL, *errout = NULL;
+ int r = commandv (&out, &errout, argv);
+
+ if (fs->type != MOUNTABLE_PATH) {
+ CLEANUP_FREE char *err = NULL;
+ if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) {
+ reply_with_error ("%s", err ? err : "malloc");
+ goto cmderror;
+ }
+
+ if (rmdir (fs_buf) == -1 && errno != ENOENT) {
+ reply_with_error ("rmdir: %m\n");
+ goto cmderror;
+ }
+ }
+
if (r == -1) {
- reply_with_error ("%s: %s", fs, err);
- return NULL;
+ CLEANUP_FREE char *fs_desc = mountable_to_string (fs);
+ if (fs_desc == NULL) {
+ fprintf (stderr, "malloc: %m");
+ }
+ reply_with_error ("%s: %s", fs_desc ? fs_desc :
"malloc", errout);
+ goto cmderror;
}
lines = split_lines (out);
- if (!lines)
- return NULL;
+ if (!lines) return NULL;
}
/* Output is:
diff --git a/generator/actions.ml b/generator/actions.ml
index 6a42bca..f17cb6a 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -9519,7 +9519,7 @@ directory and the name of the snapshot, in the form
C</path/to/dest/name>." };
{ defaults with
name = "btrfs_subvolume_list";
- style = RStructList ("subvolumes", "btrfssubvolume"),
[Pathname "fs"], [];
+ style = RStructList ("subvolumes", "btrfssubvolume"),
[Mountable_or_Path "fs"], [];
proc_nr = Some 325;
optional = Some "btrfs"; camel_name =
"BTRFSSubvolumeList";
tests = [] (* tested in tests/btrfs *);
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 3/7] mountable: Make list-filesystems return btrfsvols
---
src/listfs.c | 37 ++++++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/listfs.c b/src/listfs.c
index 4bcdf51..3e4f28e 100644
--- a/src/listfs.c
+++ b/src/listfs.c
@@ -136,6 +136,20 @@ remove_from_list (char **list, const char *item)
}
}
+static void
+add_vfs(guestfs_h *g, char *mountable, char *vfs_type,
+ char ***ret, size_t *ret_size)
+{
+ /* Extend the return array. */
+ size_t i = *ret_size;
+ *ret_size += 2;
+ *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *));
+
+ (*ret)[i] = mountable;
+ (*ret)[i+1] = vfs_type;
+ (*ret)[i+2] = NULL;
+}
+
/* Use vfs-type to look for a filesystem of some sort on 'dev'.
* Apart from some types which we ignore, add the result to the
* 'ret' string list.
@@ -157,6 +171,21 @@ check_with_vfs_type (guestfs_h *g, const char *device,
v = safe_strdup (g, "unknown");
free (vfs_type);
}
+ else if (STREQ (vfs_type, "btrfs")) {
+ struct guestfs_btrfssubvolume_list *vols +
guestfs_btrfs_subvolume_list (g, device);
+
+ for (size_t i = 0; i < vols->len; i++) {
+ struct guestfs_btrfssubvolume *this = &vols->val[i];
+ char *mountable = safe_asprintf (g, "btrfsvol:%s/%s",
+ device, this->btrfssubvolume_path);
+ add_vfs (g, mountable, safe_strdup (g, "btrfs"), ret,
ret_size);
+ }
+
+ guestfs_free_btrfssubvolume_list (vols);
+
+ v = safe_strdup (g, "btrfs");
+ }
else {
/* Ignore all "*_member" strings. In libblkid these are returned
* for things which are members of some RAID or LVM set, most
@@ -177,13 +206,7 @@ check_with_vfs_type (guestfs_h *g, const char *device,
v = vfs_type;
}
- /* Extend the return array. */
- size_t i = *ret_size;
- *ret_size += 2;
- *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *));
- (*ret)[i] = safe_strdup (g, device);
- (*ret)[i+1] = v;
- (*ret)[i+2] = NULL;
+ add_vfs (g, safe_strdup (g, device), v, ret, ret_size);
}
/* We should ignore partitions that have MBR type byte 0x42, because
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 4/7] New internal API: internal_parse_mountable
This API allows the library to parse a mountable string.
This change also moves the mountable_type_t enum into mountable.h in
the library, and includes it automatically for code defining
GUESTFS_PRIVATE. As mountable.h is not installed, this will mean that
GUESTFS_PRIVATE will not be usable outside a build tree.
---
.gitignore | 2 +
Makefile.am | 1 +
configure.ac | 1 +
daemon/Makefile.am | 21 ++--
daemon/daemon.h | 6 +-
daemon/mountable.c | 60 +++++++++
generator/actions.ml | 9 ++
generator/c.ml | 2 +
generator/structs.ml | 10 ++
po/POTFILES | 1 +
src/MAX_PROC_NR | 2 +-
src/mountable.h | 36 ++++++
tests/mountable/Makefile.am | 38 ++++++
tests/mountable/test-internal_parse_mountable.c | 156 ++++++++++++++++++++++++
14 files changed, 328 insertions(+), 17 deletions(-)
create mode 100644 daemon/mountable.c
create mode 100644 src/mountable.h
create mode 100644 tests/mountable/Makefile.am
create mode 100644 tests/mountable/test-internal_parse_mountable.c
diff --git a/.gitignore b/.gitignore
index 8b88abd..5e543e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@ Makefile.in
/daemon/guestfs_protocol.h
/daemon/install-sh
/daemon/missing
+/daemon/mountable.h
/daemon/names.c
/daemon/optgroups.c
/daemon/optgroups.h
@@ -436,6 +437,7 @@ Makefile.in
/tests/guests/ubuntu.img
/tests/guests/windows.img
/tests/mount-local/test-parallel-mount-local
+/tests/mountable/test-internal_parse_mountable
/tests/parallel/test-parallel
/tests/regressions/rhbz501893
/tests/regressions/rhbz790721
diff --git a/Makefile.am b/Makefile.am
index 842008a..73a46f8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,7 @@ endif
# Tests - order is important.
if ENABLE_APPLIANCE
+SUBDIRS += tests/mountable
SUBDIRS += tests/qemu
SUBDIRS += tests/guests
SUBDIRS += tests/c-api
diff --git a/configure.ac b/configure.ac
index be713f6..7ee04a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1546,6 +1546,7 @@ AC_CONFIG_FILES([Makefile
tests/lvm/Makefile
tests/md/Makefile
tests/mount-local/Makefile
+ tests/mountable/Makefile
tests/ntfsclone/Makefile
tests/parallel/Makefile
tests/protocol/Makefile
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index a1e5e68..fa5343a 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -26,26 +26,23 @@ generator_built = \
stubs.c \
names.c
-BUILT_SOURCES = \
- $(generator_built) \
+shared_with_library = \
guestfs_protocol.c \
guestfs_protocol.h \
- errnostring-gperf.c \
errnostring-gperf.gperf \
errnostring.c \
- errnostring.h
+ errnostring.h \
+ mountable.h
+
+BUILT_SOURCES = \
+ $(generator_built) \
+ $(shared_with_library) \
+ errnostring-gperf.c
EXTRA_DIST = \
$(BUILT_SOURCES) \
guestfsd.pod
-shared_with_library = \
- guestfs_protocol.c \
- guestfs_protocol.h \
- errnostring-gperf.gperf \
- errnostring.c \
- errnostring.h
-
$(shared_with_library): %: $(libsrcdir)/%
rm -f $@
ln $< $@
@@ -144,6 +141,8 @@ guestfsd_SOURCES = \
mktemp.c \
modprobe.c \
mount.c \
+ mountable.c \
+ mountable.h \
names.c \
ntfs.c \
ntfsclone.c \
diff --git a/daemon/daemon.h b/daemon/daemon.h
index d343dfd..bb11fe9 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -34,11 +34,7 @@
/* Mountables */
-typedef enum {
- MOUNTABLE_DEVICE, /* A bare device */
- MOUNTABLE_BTRFSVOL, /* A btrfs subvolume: device + volume */
- MOUNTABLE_PATH /* An already mounted path: device = path */
-} mountable_type_t;
+#include "mountable.h"
typedef struct {
mountable_type_t type;
diff --git a/daemon/mountable.c b/daemon/mountable.c
new file mode 100644
index 0000000..170e579
--- /dev/null
+++ b/daemon/mountable.c
@@ -0,0 +1,60 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; 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 <string.h>
+
+#include "daemon.h"
+#include "actions.h"
+#include "guestfs_protocol.h"
+
+guestfs_int_mountable_internal *
+do_internal_parse_mountable (const mountable_t *mountable)
+{
+ guestfs_int_mountable_internal *ret = calloc (1, sizeof *ret);
+ if (ret == NULL) {
+ reply_with_perror ("calloc");
+ return NULL;
+ }
+
+ ret->type = mountable->type;
+ if (mountable->device) {
+ ret->device = strdup (mountable->device);
+ if (!ret->device) {
+ reply_with_perror ("strdup");
+ free (ret);
+ return NULL;
+ }
+ }
+
+ if (mountable->volume) {
+ ret->volume = strdup (mountable->volume);
+ if (!ret->volume) {
+ reply_with_perror ("strdup");
+ free (ret->device);
+ free (ret);
+ return NULL;
+ }
+ }
+
+ fprintf (stderr, "!!!!!!=======!!!!!!!! %i %s %s\n", ret->type,
ret->device, ret->volume);
+ return ret;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index f17cb6a..cd6f9c4 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -10726,6 +10726,15 @@ you are better to use C<guestfs_mv>
instead." };
This returns C<true> if and only if C<device> refers to a whole
block
device. That is, not a partition or a logical device." };
+ { defaults with
+ name = "internal_parse_mountable";
+ style = RStruct ("ret", "mountable_internal"),
[Mountable "mountable"], [];
+ visibility = VInternal;
+ proc_nr = Some 396;
+ shortdesc = "parse a mountable string";
+ longdesc = "\
+Parse a mountable string." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/generator/c.ml b/generator/c.ml
index e2ecb8a..8e8033b 100644
--- a/generator/c.ml
+++ b/generator/c.ml
@@ -709,6 +709,8 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private
(guestfs_h *g, const char *
* they are used by some of the language bindings.
*/
+#include \"mountable.h\"
+
/* Private functions. */
extern GUESTFS_DLL_PUBLIC int guestfs___for_each_disk (guestfs_h *g, /*
virDomainPtr */ void *dom, int (*)(guestfs_h *g, const char *filename, const
char *format, int readonly, void *data), void *data);
diff --git a/generator/structs.ml b/generator/structs.ml
index 82d5b7f..353d83b 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -360,6 +360,16 @@ let structs = [
"hivex_value_h", FInt64;
];
s_camel_name = "HivexValue" };
+ { defaults with
+ s_name = "mountable_internal";
+ s_internal = true;
+ s_cols = [
+ "type", FInt32;
+ "device", FString;
+ "volume", FString;
+ ];
+ s_camel_name = "MountableInternal";
+ };
] (* end of structs *)
let lookup_struct name diff --git a/po/POTFILES b/po/POTFILES
index 7ceb594..0686966 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -64,6 +64,7 @@ daemon/mknod.c
daemon/mktemp.c
daemon/modprobe.c
daemon/mount.c
+daemon/mountable.c
daemon/names.c
daemon/ntfs.c
daemon/ntfsclone.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index e537bfe..4391a33 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-395
+396
diff --git a/src/mountable.h b/src/mountable.h
new file mode 100644
index 0000000..f95f3c9
--- /dev/null
+++ b/src/mountable.h
@@ -0,0 +1,36 @@
+/* libguestfs
+ *
+ * Copyright (C) 2013 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
+ */
+
+
+#ifndef GUESTFS_MOUNTABLE_H_
+#define GUESTFS_MOUNTABLE_H_
+
+/* The type field of a parsed mountable.
+ *
+ * This is used both by mountable_t in the daemon, and
+ * struct guestfs_int_mountable_internal in the library.
+ */
+
+typedef enum {
+ MOUNTABLE_DEVICE, /* A bare device */
+ MOUNTABLE_BTRFSVOL, /* A btrfs subvolume: device + volume */
+ MOUNTABLE_PATH /* An already mounted path: device = path */
+} mountable_type_t;
+
+#endif /* GUESTFS_MOUNTABLE_H_ */
diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am
new file mode 100644
index 0000000..d50947f
--- /dev/null
+++ b/tests/mountable/Makefile.am
@@ -0,0 +1,38 @@
+# libguestfs
+# Copyright (C) 2012 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; 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
+
+TESTS_ENVIRONMENT = $(top_builddir)/run --test
+
+TESTS=test-internal_parse_mountable
+check_PROGRAMS = test-internal_parse_mountable
+
+test_internal_parse_mountable_SOURCES = test-internal_parse_mountable.c
+test_internal_parse_mountable_CFLAGS = \
+ -DGUESTFS_WARN_DEPRECATED=1 \
+ -DGUESTFS_PRIVATE=1 \
+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
+ -I$(top_srcdir)/src -I$(top_builddir)/src \
+ $(WARN_CFLAGS) $(WERROR_CFLAGS) \
+ $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+test_internal_parse_mountable_LDADD = \
+ $(top_builddir)/src/libguestfs.la \
+ $(top_builddir)/gnulib/lib/libgnu.la
+
+check-slow:
+ $(MAKE) TESTS="test-parallel" check
diff --git a/tests/mountable/test-internal_parse_mountable.c
b/tests/mountable/test-internal_parse_mountable.c
new file mode 100644
index 0000000..0e7593d
--- /dev/null
+++ b/tests/mountable/test-internal_parse_mountable.c
@@ -0,0 +1,156 @@
+/* libguestfs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "guestfs.h"
+
+#define STREQ(a,b) (strcmp((a),(b)) == 0)
+
+#define IMG "test.img"
+
+int
+main (int argc, char *argv[])
+{
+ int fd = open (IMG, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd == -1) {
+ perror ("open " IMG);
+ exit (EXIT_FAILURE);
+ }
+
+ int r = posix_fallocate (fd, 0, 1024*1024*1024);
+ if (r != 0) {
+ fprintf (stderr, "posix_fallocate " IMG " 1G: %s\n",
strerror (r));
+ unlink (IMG);
+ exit (EXIT_FAILURE);
+ }
+
+ if (close (fd) == -1) {
+ perror ("close " IMG);
+ unlink (IMG);
+ exit (EXIT_FAILURE);
+ }
+
+ guestfs_h *g = guestfs_create ();
+ if (g == NULL) {
+ fprintf (stderr, "guestfs_create: %s\n", guestfs_last_error (g));
+ exit (EXIT_FAILURE);
+ }
+
+ if (guestfs_add_drive_opts (g, IMG,
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
+ GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
+ -1) == -1) {
+ fprintf (stderr, "guestfs_add_drive_opts: %s\n",
guestfs_last_error (g));
+
+ error:
+ guestfs_close (g);
+ unlink (IMG);
+ exit (EXIT_FAILURE);
+ }
+
+ if (guestfs_launch (g) == -1) {
+ fprintf (stderr, "guestfs_launch: %s\n", guestfs_last_error (g));
+ goto error;
+ }
+
+ if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) {
+ fprintf (stderr, "guestfs_part_disk: %s\n", guestfs_last_error
(g));
+ goto error;
+ }
+
+ if (guestfs_pvcreate (g, "/dev/sda1") == -1) {
+ fprintf (stderr, "guestfs_pvcreate: %s\n", guestfs_last_error
(g));
+ goto error;
+ }
+
+ const char *pvs[] = { "/dev/sda1", NULL };
+ if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) {
+ fprintf (stderr, "guestfs_vgcreate: %s\n", guestfs_last_error
(g));
+ goto error;
+ }
+
+ if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) {
+ fprintf (stderr, "guestfs_lvcreate: %s\n", guestfs_last_error
(g));
+ goto error;
+ }
+
+ const char *devices[] = { "/dev/VG/LV", NULL };
+ if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) {
+ fprintf (stderr, "guestfs_mkfs_btrfs: %s\n", guestfs_last_error
(g));
+ goto error;
+ }
+
+ if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) {
+ fprintf (stderr, "guestfs_mount: %s\n", guestfs_last_error (g));
+ goto error;
+ }
+
+ if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) {
+ fprintf (stderr, "guestfs_btrfs_subvolume_create: %s\n",
+ guestfs_last_error (g));
+ goto error;
+ }
+
+ #if 0
+ struct guestfs_mountable_internal *mountable +
guestfs_internal_parse_mountable (g, "/dev/VG/LV");
+ if (mountable == NULL) {
+ fprintf (stderr, "guestfs_mountable_internal /dev/VG/LV: %s\n",
+ guestfs_last_error (g));
+ goto error;
+ }
+
+ if (mountable->type != MOUNTABLE_DEVICE ||
+ !STREQ ("/dev/VG/LV", mountable->device))
+ {
+ fprintf (stderr, "incorrectly parsed /dev/VG/LV");
+ goto error;
+ }
+
+ guestfs_free_mountable_internal (mountable);
+ #endif
+
+ struct guestfs_mountable_internal *mountable +
guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv");
+ if (mountable == NULL) {
+ fprintf (stderr, "guestfs_mountable_internal /dev/VG/LV/sv:
%s\n",
+ guestfs_last_error (g));
+ goto error;
+ }
+
+ if (mountable->type != MOUNTABLE_BTRFSVOL ||
+ !STREQ ("/dev/VG/LV", mountable->device) ||
+ !STREQ ("sv", mountable->volume))
+ {
+ fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv");
+ goto error;
+ }
+ guestfs_free_mountable_internal (mountable);
+
+ guestfs_close (g);
+ unlink (IMG);
+
+ exit (EXIT_SUCCESS);
+}
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 5/7] inspect: Update inspect_os to use mountables
This fixes inspection of guests which use btrfs subvolumes.
---
src/guestfs-internal.h | 7 +--
src/inspect-fs-cd.c | 2 +-
src/inspect-fs-unix.c | 144 +++++++++++++++++++++++++++----------------------
src/inspect-fs.c | 53 +++++++++---------
src/inspect.c | 12 ++---
5 files changed, 118 insertions(+), 100 deletions(-)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index bd7c802..c52b9a5 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -391,7 +391,7 @@ enum inspect_os_package_management {
struct inspect_fs {
int is_root;
- char *device;
+ char *mountable;
enum inspect_os_type type;
enum inspect_os_distro distro;
enum inspect_os_package_format package_format;
@@ -414,7 +414,7 @@ struct inspect_fs {
};
struct inspect_fstab_entry {
- char *device;
+ char *mountable;
char *mountpoint;
};
@@ -524,7 +524,8 @@ extern struct inspect_fs *guestfs___search_for_root
(guestfs_h *g, const char *r
/* inspect-fs.c */
extern int guestfs___is_file_nocase (guestfs_h *g, const char *);
extern int guestfs___is_dir_nocase (guestfs_h *g, const char *);
-extern int guestfs___check_for_filesystem_on (guestfs_h *g, const char
*device);
+extern int guestfs___check_for_filesystem_on (guestfs_h *g,
+ const char *mountable);
extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str);
extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const
char *str);
extern int guestfs___parse_major_minor (guestfs_h *g, struct inspect_fs *fs);
diff --git a/src/inspect-fs-cd.c b/src/inspect-fs-cd.c
index e4f257f..407e4f8 100644
--- a/src/inspect-fs-cd.c
+++ b/src/inspect-fs-cd.c
@@ -503,7 +503,7 @@ guestfs___check_installer_iso (guestfs_h *g, struct
inspect_fs *fs,
return 0;
/* Otherwise we matched an ISO, so fill in the fs fields. */
- fs->device = safe_strdup (g, device);
+ fs->mountable = safe_strdup (g, device);
fs->is_root = 1;
fs->format = OS_FORMAT_INSTALLER;
fs->type = osinfo->type;
diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c
index 40f797d..26c7579 100644
--- a/src/inspect-fs-unix.c
+++ b/src/inspect-fs-unix.c
@@ -160,8 +160,7 @@ static int check_hostname_redhat (guestfs_h *g, struct
inspect_fs *fs);
static int check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs);
static int check_fstab (guestfs_h *g, struct inspect_fs *fs);
static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
- const char *spec, const char *mp,
- Hash_table *md_map);
+ const char *mountable, const char *mp);
static char *resolve_fstab_device (guestfs_h *g, const char *spec,
Hash_table *md_map);
static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char
**configfiles, int (*f) (guestfs_h *, struct inspect_fs *));
@@ -870,17 +869,13 @@ check_hostname_freebsd (guestfs_h *g, struct inspect_fs
*fs)
static int
check_fstab (guestfs_h *g, struct inspect_fs *fs)
{
- CLEANUP_FREE_STRING_LIST char **entries = NULL;
- char **entry;
- char augpath[256];
- int r;
- CLEANUP_HASH_FREE Hash_table *md_map;
-
/* Generate a map of MD device paths listed in /etc/mdadm.conf to MD device
* paths in the guestfs appliance */
+ CLEANUP_HASH_FREE Hash_table *md_map = NULL;
if (map_md_devices (g, &md_map) == -1) return -1;
- entries = guestfs_aug_match (g, "/files/etc/fstab/*[label() !=
'#comment']");
+ CLEANUP_FREE_STRING_LIST char **entries + guestfs_aug_match (g,
"/files/etc/fstab/*[label() != '#comment']");
if (entries == NULL)
return -1;
@@ -889,20 +884,81 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
return -1;
}
- for (entry = entries; *entry != NULL; entry++) {
- snprintf (augpath, sizeof augpath, "%s/spec", *entry);
- CLEANUP_FREE char *spec = guestfs_aug_get (g, augpath);
- if (spec == NULL)
- return -1;
+ for (char **entry = entries; *entry != NULL; entry++) {
+ char augpath[256];
snprintf (augpath, sizeof augpath, "%s/file", *entry);
CLEANUP_FREE char *mp = guestfs_aug_get (g, augpath);
- if (mp == NULL)
- return -1;
+ if (mp == NULL) return -1;
+
+ /* Ignore certain mountpoints. */
+ if (STRPREFIX (mp, "/dev/") ||
+ STREQ (mp, "/dev") ||
+ STRPREFIX (mp, "/media/") ||
+ STRPREFIX (mp, "/proc/") ||
+ STREQ (mp, "/proc") ||
+ STRPREFIX (mp, "/selinux/") ||
+ STREQ (mp, "/selinux") ||
+ STRPREFIX (mp, "/sys/") ||
+ STREQ (mp, "/sys"))
+ continue;
- r = add_fstab_entry (g, fs, spec, mp, md_map);
- if (r == -1)
- return -1;
+ snprintf (augpath, sizeof augpath, "%s/spec", *entry);
+ CLEANUP_FREE char *spec = guestfs_aug_get (g, augpath);
+ if (spec == NULL) return -1;
+
+ /* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */
+ if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7]))
||
+ STREQ (spec, "/dev/floppy") ||
+ STREQ (spec, "/dev/cdrom"))
+ continue;
+
+ /* Resolve UUID= and LABEL= to the actual device. */
+ CLEANUP_FREE char *mountable = NULL;
+ if (STRPREFIX (spec, "UUID="))
+ mountable = guestfs_findfs_uuid (g, &spec[5]);
+ else if (STRPREFIX (spec, "LABEL="))
+ mountable = guestfs_findfs_label (g, &spec[6]);
+ /* Ignore "/.swap" (Pardus) and pseudo-devices like
"tmpfs". */
+ else if (STREQ (spec, "/dev/root"))
+ /* Resolve /dev/root to the current device. */
+ mountable = safe_strdup (g, fs->mountable);
+ else if (STRPREFIX (spec, "/dev/"))
+ /* Resolve guest block device names. */
+ mountable = resolve_fstab_device (g, spec, md_map);
+
+ /* If we haven't resolved the device successfully by this point,
+ * we don't care, just ignore it.
+ */
+ if (mountable == NULL)
+ continue;
+
+ snprintf (augpath, sizeof augpath, "%s/vfstype", *entry);
+ CLEANUP_FREE char *vfstype = guestfs_aug_get (g, augpath);
+ if (vfstype == NULL) return -1;
+
+ if (STREQ (vfstype, "btrfs")) {
+ snprintf (augpath, sizeof augpath, "%s/opt", *entry);
+ CLEANUP_FREE_STRING_LIST char **opts = guestfs_aug_match (g, augpath);
+ if (opts == NULL) return -1;
+
+ for (char **opt = opts; *opt; opt++) {
+ CLEANUP_FREE char *optname = guestfs_aug_get (g, augpath);
+ if (optname == NULL) return -1;
+
+ if (STREQ (optname, "subvol")) {
+ snprintf (augpath, sizeof augpath, "%s/value", *opt);
+ CLEANUP_FREE char *subvol = guestfs_aug_get (g, augpath);
+ if (subvol == NULL) return -1;
+
+ char *new = safe_asprintf (g, "btrfsvol:%s/%s", mountable,
subvol);
+ free (mountable);
+ mountable = new;
+ }
+ }
+ }
+
+ if (add_fstab_entry (g, fs, mountable, mp) == -1) return -1;
}
return 0;
@@ -918,48 +974,8 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
*/
static int
add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
- const char *spec, const char *mp, Hash_table *md_map)
+ const char *mountable, const char *mountpoint)
{
- /* Ignore certain mountpoints. */
- if (STRPREFIX (mp, "/dev/") ||
- STREQ (mp, "/dev") ||
- STRPREFIX (mp, "/media/") ||
- STRPREFIX (mp, "/proc/") ||
- STREQ (mp, "/proc") ||
- STRPREFIX (mp, "/selinux/") ||
- STREQ (mp, "/selinux") ||
- STRPREFIX (mp, "/sys/") ||
- STREQ (mp, "/sys"))
- return 0;
-
- /* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */
- if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) ||
- STREQ (spec, "/dev/floppy") ||
- STREQ (spec, "/dev/cdrom"))
- return 0;
-
- /* Resolve UUID= and LABEL= to the actual device. */
- char *device = NULL;
- if (STRPREFIX (spec, "UUID="))
- device = guestfs_findfs_uuid (g, &spec[5]);
- else if (STRPREFIX (spec, "LABEL="))
- device = guestfs_findfs_label (g, &spec[6]);
- /* Ignore "/.swap" (Pardus) and pseudo-devices like
"tmpfs". */
- else if (STREQ (spec, "/dev/root"))
- /* Resolve /dev/root to the current device. */
- device = safe_strdup (g, fs->device);
- else if (STRPREFIX (spec, "/dev/"))
- /* Resolve guest block device names. */
- device = resolve_fstab_device (g, spec, md_map);
-
- /* If we haven't resolved the device successfully by this point,
- * we don't care, just ignore it.
- */
- if (device == NULL)
- return 0;
-
- char *mountpoint = safe_strdup (g, mp);
-
/* Add this to the fstab entry in 'fs'.
* Note these are further filtered by guestfs_inspect_get_mountpoints
* and guestfs_inspect_get_filesystems.
@@ -970,8 +986,6 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
p = realloc (fs->fstab, n * sizeof (struct inspect_fstab_entry));
if (p == NULL) {
perrorf (g, "realloc");
- free (device);
- free (mountpoint);
return -1;
}
@@ -979,10 +993,10 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
fs->nr_fstab = n;
/* These are owned by the handle and freed by guestfs___free_inspect_info. */
- fs->fstab[n-1].device = device;
- fs->fstab[n-1].mountpoint = mountpoint;
+ fs->fstab[n-1].mountable = safe_strdup (g, mountable);
+ fs->fstab[n-1].mountpoint = safe_strdup (g, mountpoint);
- debug (g, "fstab: device=%s mountpoint=%s", device, mountpoint);
+ debug (g, "fstab: mountable=%s mountpoint=%s", mountable,
mountpoint);
return 0;
}
diff --git a/src/inspect-fs.c b/src/inspect-fs.c
index be22eb0..8a88822 100644
--- a/src/inspect-fs.c
+++ b/src/inspect-fs.c
@@ -79,7 +79,8 @@ free_regexps (void)
pcre_free (re_major_minor);
}
-static int check_filesystem (guestfs_h *g, const char *device,
+static int check_filesystem (guestfs_h *g, const char *mountable,
+ const struct guestfs_mountable_internal *m,
int whole_device);
static int extend_fses (guestfs_h *g);
@@ -87,7 +88,7 @@ static int extend_fses (guestfs_h *g);
* another entry in g->fses.
*/
int
-guestfs___check_for_filesystem_on (guestfs_h *g, const char *device)
+guestfs___check_for_filesystem_on (guestfs_h *g, const char *mountable)
{
CLEANUP_FREE char *vfs_type = NULL;
int is_swap, r;
@@ -98,25 +99,31 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char
*device)
* temporarily replace the error handler with a null one.
*/
guestfs_push_error_handler (g, NULL, NULL);
- vfs_type = guestfs_vfs_type (g, device);
+ vfs_type = guestfs_vfs_type (g, mountable);
guestfs_pop_error_handler (g);
is_swap = vfs_type && STREQ (vfs_type, "swap");
debug (g, "check_for_filesystem_on: %s (%s)",
- device, vfs_type ? vfs_type : "failed to get vfs type");
+ mountable, vfs_type ? vfs_type : "failed to get vfs type");
if (is_swap) {
if (extend_fses (g) == -1)
return -1;
fs = &g->fses[g->nr_fses-1];
- fs->device = safe_strdup (g, device);
+ fs->mountable = safe_strdup (g, mountable);
return 0;
}
+ struct guestfs_mountable_internal *m + guestfs_internal_parse_mountable
(g, mountable);
+
/* If it's a whole device, see if it is an install ISO. */
- int whole_device = guestfs_is_whole_device (g, device);
- if (whole_device == -1) {
- return -1;
+ int whole_device = 0;
+ if (m->type == MOUNTABLE_DEVICE) {
+ whole_device = guestfs_is_whole_device (g, m->device);
+ if (whole_device == -1) {
+ return -1;
+ }
}
if (whole_device) {
@@ -124,7 +131,7 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char
*device)
return -1;
fs = &g->fses[g->nr_fses-1];
- r = guestfs___check_installer_iso (g, fs, device);
+ r = guestfs___check_installer_iso (g, fs, m->device);
if (r == -1) { /* Fatal error. */
g->nr_fses--;
return -1;
@@ -140,19 +147,19 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const
char *device)
guestfs_push_error_handler (g, NULL, NULL);
if (vfs_type && STREQ (vfs_type, "ufs")) { /* Hack for the
*BSDs. */
/* FreeBSD fs is a variant of ufs called ufs2 ... */
- r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs",
device, "/");
+ r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs",
mountable, "/");
if (r == -1)
/* while NetBSD and OpenBSD use another variant labeled 44bsd */
- r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs",
device, "/");
+ r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs",
mountable, "/");
} else {
- r = guestfs_mount_ro (g, device, "/");
+ r = guestfs_mount_ro (g, mountable, "/");
}
guestfs_pop_error_handler (g);
if (r == -1)
return 0;
/* Do the rest of the checks. */
- r = check_filesystem (g, device, whole_device);
+ r = check_filesystem (g, mountable, m, whole_device);
/* Unmount the filesystem. */
if (guestfs_umount_all (g) == -1)
@@ -161,28 +168,24 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const
char *device)
return r;
}
-/* is_block and is_partnum are just hints: is_block is true if the
- * filesystem is a whole block device (eg. /dev/sda). is_partnum
- * is > 0 if the filesystem is a direct partition, and in this case
- * it is the partition number counting from 1
- * (eg. /dev/sda1 => is_partnum == 1).
- */
static int
-check_filesystem (guestfs_h *g, const char *device, int whole_device)
+check_filesystem (guestfs_h *g, const char *mountable,
+ const struct guestfs_mountable_internal *m,
+ int whole_device)
{
if (extend_fses (g) == -1)
return -1;
int partnum = -1;
- if (!whole_device) {
+ if (!whole_device && m->type == MOUNTABLE_DEVICE) {
guestfs_push_error_handler (g, NULL, NULL);
- partnum = guestfs_part_to_partnum (g, device);
+ partnum = guestfs_part_to_partnum (g, m->device);
guestfs_pop_error_handler (g);
}
struct inspect_fs *fs = &g->fses[g->nr_fses-1];
- fs->device = safe_strdup (g, device);
+ fs->mountable = safe_strdup (g, mountable);
/* Optimize some of the tests by avoiding multiple tests of the same thing.
*/
int is_dir_etc = guestfs_is_dir (g, "/etc") > 0;
@@ -203,7 +206,7 @@ check_filesystem (guestfs_h *g, const char *device, int
whole_device)
* that is probably /dev/sda5 (see:
* http://www.freebsd.org/doc/handbook/disk-organization.html)
*/
- if (match (g, device, re_first_partition))
+ if (m->type == MOUNTABLE_DEVICE && match (g, m->device,
re_first_partition))
return 0;
fs->is_root = 1;
@@ -219,7 +222,7 @@ check_filesystem (guestfs_h *g, const char *device, int
whole_device)
* that is probably /dev/sda5 (see:
* http://www.freebsd.org/doc/handbook/disk-organization.html)
*/
- if (match (g, device, re_first_partition))
+ if (m->type == MOUNTABLE_DEVICE && match (g, m->device,
re_first_partition))
return 0;
fs->is_root = 1;
diff --git a/src/inspect.c b/src/inspect.c
index ae746cb..f031434 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -107,7 +107,7 @@ guestfs__inspect_get_roots (guestfs_h *g)
count = 0;
for (i = 0; i < g->nr_fses; ++i) {
if (g->fses[i].is_root) {
- ret[count] = safe_strdup (g, g->fses[i].device);
+ ret[count] = safe_strdup (g, g->fses[i].mountable);
count++;
}
}
@@ -347,7 +347,7 @@ guestfs__inspect_get_mountpoints (guestfs_h *g, const char
*root)
for (i = 0; i < nr; ++i)
if (CRITERION (fs, i)) {
ret[2*count] = safe_strdup (g, fs->fstab[i].mountpoint);
- ret[2*count+1] = safe_strdup (g, fs->fstab[i].device);
+ ret[2*count+1] = safe_strdup (g, fs->fstab[i].mountable);
count++;
}
#undef CRITERION
@@ -379,7 +379,7 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char
*root)
}
for (i = 0; i < nr; ++i)
- ret[i] = safe_strdup (g, fs->fstab[i].device);
+ ret[i] = safe_strdup (g, fs->fstab[i].mountable);
return ret;
}
@@ -485,7 +485,7 @@ guestfs___free_inspect_info (guestfs_h *g)
{
size_t i;
for (i = 0; i < g->nr_fses; ++i) {
- free (g->fses[i].device);
+ free (g->fses[i].mountable);
free (g->fses[i].product_name);
free (g->fses[i].product_variant);
free (g->fses[i].arch);
@@ -494,7 +494,7 @@ guestfs___free_inspect_info (guestfs_h *g)
free (g->fses[i].windows_current_control_set);
size_t j;
for (j = 0; j < g->fses[i].nr_fstab; ++j) {
- free (g->fses[i].fstab[j].device);
+ free (g->fses[i].fstab[j].mountable);
free (g->fses[i].fstab[j].mountpoint);
}
free (g->fses[i].fstab);
@@ -608,7 +608,7 @@ guestfs___search_for_root (guestfs_h *g, const char *root)
struct inspect_fs *fs;
for (i = 0; i < g->nr_fses; ++i) {
fs = &g->fses[i];
- if (fs->is_root && STREQ (root, fs->device))
+ if (fs->is_root && STREQ (root, fs->mountable))
return fs;
}
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 6/7] btrfs: Make a stub Fedora btrfs guest for inspection testing
---
.gitignore | 1 +
tests/guests/Makefile.am | 5 ++
tests/guests/guest-aux/make-fedora-img.pl | 81 +++++++++++++++++++++++--------
3 files changed, 66 insertions(+), 21 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5e543e9..0c9545b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -429,6 +429,7 @@ Makefile.in
/tests/data/test.iso
/tests/guests/debian.img
/tests/guests/fedora.img
+/tests/guests/fedora-btrfs.img
/tests/guests/fedora-md1.img
/tests/guests/fedora-md2.img
/tests/guests/guest-aux/fedora-name.db
diff --git a/tests/guests/Makefile.am b/tests/guests/Makefile.am
index 347aef5..d2291c5 100644
--- a/tests/guests/Makefile.am
+++ b/tests/guests/Makefile.am
@@ -58,6 +58,11 @@ stamp-fedora-md.img: guest-aux/make-fedora-img.pl \
SRCDIR=$(srcdir) LAYOUT=partitions-md $(top_builddir)/run --test $<
touch $@
+fedora-btrfs.img: guest-aux/make-fedora-img.pl \
+ guest-aux/fedora-name.db \
+ guest-aux/fedora-packages.db
+ SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test $<
+
guest-aux/fedora-name.db: guest-aux/fedora-name.db.txt
rm -f $@ $@-t
mkdir -p guest-aux
diff --git a/tests/guests/guest-aux/make-fedora-img.pl
b/tests/guests/guest-aux/make-fedora-img.pl
index 3272d4c..1875602 100755
--- a/tests/guests/guest-aux/make-fedora-img.pl
+++ b/tests/guests/guest-aux/make-fedora-img.pl
@@ -31,7 +31,6 @@ my @images;
my $g = Sys::Guestfs->new ();
my $bootdev;
-my $rootdev;
foreach ('LAYOUT', 'SRCDIR') {
defined ($ENV{$_}) or die "Missing environment variable: $_";
@@ -48,7 +47,6 @@ EOF
close ($fstab) or die;
$bootdev = '/dev/sda1';
- $rootdev = '/dev/sda2';
open (my $img, '>', "fedora.img.tmp.$$") or die;
truncate ($img, 512*1024*1024) or die;
@@ -60,6 +58,8 @@ EOF
$g->part_init ('/dev/sda', 'mbr');
$g->part_add ('/dev/sda', 'p', 64, 524287);
$g->part_add ('/dev/sda', 'p', 524288, -64);
+
+ init_lvm_root ('/dev/sda2');
}
elsif ($ENV{LAYOUT} eq 'partitions-md') {
@@ -73,7 +73,6 @@ EOF
close ($fstab) or die;
$bootdev = '/dev/md/boot';
- $rootdev = '/dev/md/root';
foreach my $img (@images) {
open (my $fh, '>', $img) or die;
@@ -110,6 +109,41 @@ EOF
}
close ($mdadm) or die;
+
+ init_lvm_root ('/dev/md/root');
+}
+
+elsif ($ENV{LAYOUT} eq 'btrfs') {
+ push (@images, "fedora-btrfs.img.tmp.$$");
+
+ open (my $fstab, '>', "fstab.tmp.$$") or die;
+ print $fstab <<EOF;
+LABEL=BOOT /boot ext2 default 0 0
+LABEL=ROOT / btrfs subvol=root 0 0
+LABEL=ROOT /home btrfs subvol=home 0 0
+EOF
+ close ($fstab) or die;
+
+ $bootdev = '/dev/sda1';
+
+ open (my $img, '>', "fedora-btrfs.img.tmp.$$") or die;
+ truncate ($img, 512*1024*1024) or die;
+ close ($img) or die;
+
+ $g->add_drive ("fedora-btrfs.img.tmp.$$");
+ $g->launch ();
+
+ $g->part_init ('/dev/sda', 'mbr');
+ $g->part_add ('/dev/sda', 'p', 64, 524287);
+ $g->part_add ('/dev/sda', 'p', 524288, -64);
+
+ $g->mkfs_btrfs (['/dev/sda2'], label => 'ROOT');
+ $g->mount ('/dev/sda2', '/');
+ $g->btrfs_subvolume_create ('/root');
+ $g->btrfs_subvolume_create ('/home');
+ $g->umount ('/');
+
+ $g->mount ('btrfsvol:/dev/sda2/root', '/');
}
else {
@@ -117,25 +151,36 @@ else {
exit 1;
}
-$g->pvcreate ($rootdev);
-$g->vgcreate ('VG', [$rootdev]);
-$g->lvcreate ('Root', 'VG', 32);
-$g->lvcreate ('LV1', 'VG', 32);
-$g->lvcreate ('LV2', 'VG', 32);
-$g->lvcreate ('LV3', 'VG', 64);
+sub init_lvm_root {
+ my ($rootdev) = @_;
+
+ $g->pvcreate ($rootdev);
+ $g->vgcreate ('VG', [$rootdev]);
+ $g->lvcreate ('Root', 'VG', 32);
+ $g->lvcreate ('LV1', 'VG', 32);
+ $g->lvcreate ('LV2', 'VG', 32);
+ $g->lvcreate ('LV3', 'VG', 64);
+
+ # Phony root filesystem.
+ $g->mkfs ('ext2', '/dev/VG/Root', blocksize => 4096);
+ $g->set_label ('/dev/VG/Root', 'ROOT');
+ $g->set_e2uuid ('/dev/VG/Root',
'01234567-0123-0123-0123-012345678902');
+
+ # Other filesystems.
+ # Note that these should be empty, for testing virt-df.
+ $g->mkfs ('ext2', '/dev/VG/LV1', blocksize => 4096);
+ $g->mkfs ('ext2', '/dev/VG/LV2', blocksize => 1024);
+ $g->mkfs ('ext2', '/dev/VG/LV3', blocksize => 2048);
+
+ $g->mount ('/dev/VG/Root', '/');
+}
# Phony /boot filesystem
$g->mkfs ('ext2', $bootdev, blocksize => 4096);
$g->set_label ($bootdev, 'BOOT');
$g->set_e2uuid ($bootdev, '01234567-0123-0123-0123-012345678901');
-# Phony root filesystem.
-$g->mkfs ('ext2', '/dev/VG/Root', blocksize => 4096);
-$g->set_label ('/dev/VG/Root', 'ROOT');
-$g->set_e2uuid ('/dev/VG/Root',
'01234567-0123-0123-0123-012345678902');
-
# Enough to fool inspection API.
-$g->mount ('/dev/VG/Root', '/');
$g->mkdir ('/boot');
$g->mount ($bootdev, '/boot');
$g->mkdir ('/bin');
@@ -188,12 +233,6 @@ $g->ln_s ('/bin/test1', '/bin/test5');
$g->mkfifo (0777, '/bin/test6');
$g->mknod (0777, 10, 10, '/bin/test7');
-# Other filesystems.
-# Note that these should be empty, for testing virt-df.
-$g->mkfs ('ext2', '/dev/VG/LV1', blocksize => 4096);
-$g->mkfs ('ext2', '/dev/VG/LV2', blocksize => 1024);
-$g->mkfs ('ext2', '/dev/VG/LV3', blocksize => 2048);
-
# Cleanup
$g->shutdown ();
$g->close ();
--
1.8.1.2
Matthew Booth
2013-Feb-12 11:04 UTC
[Libguestfs] [PATCH 7/7] mountable: Test inspection of fedora image
--- tests/mountable/Makefile.am | 2 +- tests/mountable/test-inspect.sh | 57 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100755 tests/mountable/test-inspect.sh diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am index d50947f..f4b6e01 100644 --- a/tests/mountable/Makefile.am +++ b/tests/mountable/Makefile.am @@ -19,7 +19,7 @@ include $(top_srcdir)/subdir-rules.mk TESTS_ENVIRONMENT = $(top_builddir)/run --test -TESTS=test-internal_parse_mountable +TESTS=test-internal_parse_mountable test-inspect.sh check_PROGRAMS = test-internal_parse_mountable test_internal_parse_mountable_SOURCES = test-internal_parse_mountable.c diff --git a/tests/mountable/test-inspect.sh b/tests/mountable/test-inspect.sh new file mode 100755 index 0000000..2ad3c1b --- /dev/null +++ b/tests/mountable/test-inspect.sh @@ -0,0 +1,57 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2013 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +set -e +export LANG=C + +guestfish=../../fish/guestfish +canonical="sed s,/dev/vd,/dev/sd,g" + +rm -f test.qcow2 test.output + +# Start with the regular (good) fedora image, modify /etc/fstab +# and then inspect it. +qemu-img create -F raw -b ../guests/fedora-btrfs.img -f qcow2 test.qcow2 + +# Test that basic inspection works and the expected filesystems are +# found +$guestfish -a test.qcow2 -i <<'EOF' | sort | $canonical > test.output + inspect-get-mountpoints btrfsvol:/dev/sda2/root +EOF + +if [ "$(cat test.output)" != "/: btrfsvol:/dev/sda2/root +/boot: /dev/sda1 +/home: btrfsvol:/dev/sda2/home" ]; then + echo "$0: error #1: unexpected output from inspect-get-mountpoints" + cat test.output + exit 1 +fi + +# Additional sanity check: did we get the release name right? +$guestfish -a test.qcow2 -i <<'EOF' > test.output + inspect-get-product-name btrfsvol:/dev/sda2/root +EOF + +if [ "$(cat test.output)" != "Fedora release 14 (Phony)"]; then + echo "$0: error #2: unexpected output from inspect-get-product-name" + cat test.output + exit 1 +fi + +rm test.qcow2 +rm test.output -- 1.8.1.2
Apparently Analagous Threads
- [PATCH 01/12] generator: Add new Mountable argument type
- [PATCH v10 00/10] Reimplement inspection in the daemon.
- [PATCH v9 00/11] Reimplement inspection in the daemon.
- [PATCH v12 00/11] Reimplement inspection in the daemon.
- [PATCH v11 00/10] Reimplement inspection in the daemon.