summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-06-09 13:42:13 +0100
committerRichard W.M. Jones <rjones@redhat.com>2012-06-09 14:52:39 +0100
commit4ba6aa3eaeb112a1468ad9189120d12e1df23709 (patch)
treee2606f99e5d6f69eaeacae3595e24755966feca5
parent4f671c829e33a218309f332621802d8d6f8d5040 (diff)
downloadlibguestfs-4ba6aa3eaeb112a1468ad9189120d12e1df23709.tar.gz
libguestfs-4ba6aa3eaeb112a1468ad9189120d12e1df23709.tar.xz
libguestfs-4ba6aa3eaeb112a1468ad9189120d12e1df23709.zip
New API: filesystem-available: tests for filesystem availability.
This also creates an internal filesystem_available function within the daemon.
-rw-r--r--daemon/available.c79
-rw-r--r--daemon/daemon.h3
-rw-r--r--generator/generator_actions.ml21
-rw-r--r--src/MAX_PROC_NR2
-rw-r--r--src/guestfs.pod10
5 files changed, 113 insertions, 2 deletions
diff --git a/daemon/available.c b/daemon/available.c
index 97f15584..08e72f30 100644
--- a/daemon/available.c
+++ b/daemon/available.c
@@ -22,9 +22,12 @@
#include <stdlib.h>
#include <string.h>
+#include "c-ctype.h"
+
#include "guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
int
do_available (char *const *groups)
@@ -70,3 +73,79 @@ do_available_all_groups (void)
return groups.argv; /* caller frees */
}
+
+/* Search for filesystem in /proc/filesystems, ignoring "nodev". */
+static int
+test_proc_filesystems (const char *filesystem)
+{
+ size_t len = strlen (filesystem) + 32;
+ char regex[len];
+ char *err;
+ int r;
+
+ snprintf (regex, len, "^[[:space:]]*%s$", filesystem);
+
+ r = commandr (NULL, &err, "grep", regex, "/proc/filesystems", NULL);
+ if (r == -1 || r >= 2) {
+ fprintf (stderr, "grep /proc/filesystems: %s", err);
+ free (err);
+ return -1;
+ }
+ free (err);
+
+ return r == 0;
+}
+
+/* Do modprobe, ignore any errors. */
+static void
+modprobe (const char *module)
+{
+ command (NULL, NULL, "modprobe", module, NULL);
+}
+
+/* Internal function for testing if a filesystem is available. Note
+ * this must not call reply_with_error functions.
+ */
+int
+filesystem_available (const char *filesystem)
+{
+ int r;
+
+ r = test_proc_filesystems (filesystem);
+ if (r == -1 || r > 0)
+ return r;
+
+ /* Not found: try to modprobe the module, then test again. */
+ if (optgroup_linuxmodules_available ()) {
+ modprobe (filesystem);
+
+ r = test_proc_filesystems (filesystem);
+ if (r == -1)
+ return -1;
+ }
+
+ return r;
+}
+
+int
+do_filesystem_available (const char *filesystem)
+{
+ size_t i, len = strlen (filesystem);
+ int r;
+
+ for (i = 0; i < len; ++i) {
+ if (!c_isalnum (filesystem[i]) && filesystem[i] != '_') {
+ reply_with_error ("filesystem name contains non-alphanumeric characters");
+ return -1;
+ }
+ }
+
+ r = filesystem_available (filesystem);
+ if (r == -1) {
+ reply_with_error ("error testing for filesystem availability; "
+ "enable verbose mode and look at preceeding output");
+ return -1;
+ }
+
+ return r;
+}
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 9dfaa4f3..af81a9da 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -151,6 +151,9 @@ struct optgroup {
};
extern struct optgroup optgroups[];
+/*-- in available.c --*/
+extern int filesystem_available (const char *filesystem);
+
/*-- in sync.c --*/
/* Use this as a replacement for sync(2). */
extern int sync_disks (void);
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 4dc46385..d88d54f2 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -5325,7 +5325,9 @@ versions of libguestfs all you could do would be to speculatively
execute a command to find out if the daemon implemented it.
See also C<guestfs_version>.
-=back");
+=back
+
+See also C<guestfs_filesystem_available>.");
("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"], []), 217, [DeprecatedBy "copy_device_to_device"],
[InitScratchFS, Always, TestOutputBuffer (
@@ -7241,6 +7243,23 @@ a btrfs filesystem.");
Used to check a btrfs filesystem, C<device> is the device file where the
filesystem is stored.");
+ ("filesystem_available", (RBool "fsavail", [String "filesystem"], []), 333, [],
+ [],
+ "check if filesystem is available",
+ "\
+Check whether libguestfs supports the named filesystem.
+The argument C<filesystem> is a filesystem name, such as
+C<ext3>.
+
+You must call C<guestfs_launch> before using this command.
+
+This is mainly useful as a negative test. If this returns true,
+it doesn't mean that a particular filesystem can be mounted,
+since filesystems can fail for other reasons such as it being
+a later version of the filesystem, or having incompatible features.
+
+See also C<guestfs_available>, L<guestfs(3)/AVAILABILITY>.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 6f96da66..55bd0ac4 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-332
+333
diff --git a/src/guestfs.pod b/src/guestfs.pod
index afdcb487..bd61c831 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -1602,6 +1602,16 @@ supports the functionality.
@AVAILABILITY@
+=head2 FILESYSTEM AVAILABLE
+
+The L</guestfs_filesystem_available> call tests whether a
+filesystem type is supported by the appliance kernel.
+
+This is mainly useful as a negative test. If this returns true,
+it doesn't mean that a particular filesystem can be mounted,
+since filesystems can fail for other reasons such as it being
+a later version of the filesystem, or having incompatible features.
+
=head2 GUESTFISH supported COMMAND
In L<guestfish(3)> there is a handy interactive command