diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-06-09 13:42:13 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-06-09 14:52:39 +0100 |
commit | 4ba6aa3eaeb112a1468ad9189120d12e1df23709 (patch) | |
tree | e2606f99e5d6f69eaeacae3595e24755966feca5 | |
parent | 4f671c829e33a218309f332621802d8d6f8d5040 (diff) | |
download | libguestfs-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.c | 79 | ||||
-rw-r--r-- | daemon/daemon.h | 3 | ||||
-rw-r--r-- | generator/generator_actions.ml | 21 | ||||
-rw-r--r-- | src/MAX_PROC_NR | 2 | ||||
-rw-r--r-- | src/guestfs.pod | 10 |
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 |