From 7d976657e6f02ca0b61858f668ae792a70327309 Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Wed, 6 Feb 2013 10:32:35 +0000 Subject: [PATCH] New internal API: internal_parse_mountable --- .gitignore | 1 + Makefile.am | 1 + configure.ac | 1 + daemon/Makefile.am | 1 + daemon/daemon.h | 6 - daemon/mountable.c | 59 +++++++++ generator/actions.ml | 9 ++ generator/structs.ml | 10 ++ po/POTFILES | 1 + src/MAX_PROC_NR | 2 +- src/guestfs-internal-all.h | 12 ++ tests/mountable/Makefile.am | 36 ++++++ .../mountable/test-internal-parse-mountable.c | 117 ++++++++++++++++++ 13 files changed, 249 insertions(+), 7 deletions(-) create mode 100644 daemon/mountable.c create mode 100644 tests/mountable/Makefile.am create mode 100644 tests/mountable/test-internal-parse-mountable.c diff --git a/.gitignore b/.gitignore index b8bea9b0b..f190cc85e 100644 --- a/.gitignore +++ b/.gitignore @@ -437,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 842008ad2..73a46f8f6 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 be713f639..7ee04a8d4 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 024aa6a0c..a57b7f380 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -140,6 +140,7 @@ guestfsd_SOURCES = \ mktemp.c \ modprobe.c \ mount.c \ + mountable.c \ names.c \ ntfs.c \ ntfsclone.c \ diff --git a/daemon/daemon.h b/daemon/daemon.h index d343dfdf4..04f28bb85 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -34,12 +34,6 @@ /* 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; - typedef struct { mountable_type_t type; const char *device; diff --git a/daemon/mountable.c b/daemon/mountable.c new file mode 100644 index 000000000..610633ee9 --- /dev/null +++ b/daemon/mountable.c @@ -0,0 +1,59 @@ +/* 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 + +#include +#include +#include + +#include "daemon.h" +#include "actions.h" +#include "guestfs_protocol.h" + +guestfs_int_internal_mountable * +do_internal_parse_mountable (const mountable_t *mountable) +{ + guestfs_int_internal_mountable *ret = calloc (1, sizeof *ret); + if (ret == NULL) { + reply_with_perror ("calloc"); + return NULL; + } + + ret->im_type = mountable->type; + if (mountable->device) { + ret->im_device = strdup (mountable->device); + if (!ret->im_device) { + reply_with_perror ("strdup"); + free (ret); + return NULL; + } + } + + if (mountable->volume) { + ret->im_volume = strdup (mountable->volume); + if (!ret->im_volume) { + reply_with_perror ("strdup"); + free (ret->im_device); + free (ret); + return NULL; + } + } + + return ret; +} diff --git a/generator/actions.ml b/generator/actions.ml index f17cb6ac2..1399fd4f2 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -10726,6 +10726,15 @@ you are better to use C instead." }; This returns C if and only if C refers to a whole block device. That is, not a partition or a logical device." }; + { defaults with + name = "internal_parse_mountable"; + style = RStruct ("mountable", "internal_mountable"), [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/structs.ml b/generator/structs.ml index 82d5b7f84..3f1037ac6 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 = "internal_mountable"; + s_internal = true; + s_cols = [ + "im_type", FInt32; + "im_device", FString; + "im_volume", FString; + ]; + s_camel_name = "InternalMountable"; + }; ] (* end of structs *) let lookup_struct name = diff --git a/po/POTFILES b/po/POTFILES index 7ceb59438..068696627 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 e537bfeb0..4391a3343 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -395 +396 diff --git a/src/guestfs-internal-all.h b/src/guestfs-internal-all.h index 9ef8ab11f..11fc0b520 100644 --- a/src/guestfs-internal-all.h +++ b/src/guestfs-internal-all.h @@ -66,4 +66,16 @@ #define xdr_uint32_t xdr_u_int32_t #endif +/* 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_INTERNAL_ALL_H_ */ diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am new file mode 100644 index 000000000..29c7a3560 --- /dev/null +++ b/tests/mountable/Makefile.am @@ -0,0 +1,36 @@ +# 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_CPPFLAGS = \ + -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 +test_internal_parse_mountable_CFLAGS = \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) \ + $(GPROF_CFLAGS) $(GCOV_CFLAGS) +test_internal_parse_mountable_LDADD = \ + $(top_builddir)/src/libguestfs.la \ + $(top_builddir)/gnulib/lib/libgnu.la diff --git a/tests/mountable/test-internal-parse-mountable.c b/tests/mountable/test-internal-parse-mountable.c new file mode 100644 index 000000000..774255106 --- /dev/null +++ b/tests/mountable/test-internal-parse-mountable.c @@ -0,0 +1,117 @@ +/* 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 + +#include +#include +#include +#include +#include + +#include "guestfs.h" +#include "guestfs-internal-all.h" + +#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) { + exit (EXIT_FAILURE); + } + + if (guestfs_add_drive_opts (g, IMG, + GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", + GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, + -1) == -1) { + error: + guestfs_close (g); + unlink (IMG); + exit (EXIT_FAILURE); + } + + if (guestfs_launch (g) == -1) goto error; + + if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) goto error; + + if (guestfs_pvcreate (g, "/dev/sda1") == -1) goto error; + + const char *pvs[] = { "/dev/sda1", NULL }; + if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) goto error; + + if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) goto error; + + const char *devices[] = { "/dev/VG/LV", NULL }; + if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) goto error; + + if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) goto error; + + if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) goto error; + + struct guestfs_internal_mountable *mountable = + guestfs_internal_parse_mountable (g, "/dev/VG/LV"); + if (mountable == NULL) goto error; + + if (mountable->im_type != MOUNTABLE_DEVICE || + !STREQ ("/dev/VG/LV", mountable->im_device)) + { + fprintf (stderr, "incorrectly parsed /dev/VG/LV"); + goto error; + } + + guestfs_free_internal_mountable (mountable); + + mountable = + guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv"); + if (mountable == NULL) goto error; + + if (mountable->im_type != MOUNTABLE_BTRFSVOL || + !STREQ ("/dev/VG/LV", mountable->im_device) || + !STREQ ("sv", mountable->im_volume)) + { + fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv"); + goto error; + } + guestfs_free_internal_mountable (mountable); + + guestfs_close (g); + unlink (IMG); + + exit (EXIT_SUCCESS); +}