summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-11-20 14:10:06 +0000
committerRichard Jones <rjones@redhat.com>2009-11-20 18:03:36 +0000
commit2d9953097b6d3b71122d444a4550047e97aee009 (patch)
tree6737890f7e75cc83b635eccf2fb839b5cec3c616 /daemon
parent8fd7f255d611d2092a244c4a48c6b7b4529e98b1 (diff)
downloadlibguestfs-2d9953097b6d3b71122d444a4550047e97aee009.tar.gz
libguestfs-2d9953097b6d3b71122d444a4550047e97aee009.tar.xz
libguestfs-2d9953097b6d3b71122d444a4550047e97aee009.zip
availability: Add optional groups and implement guestfs_available call.
The current groups are defined very conservatively using the following criteria: (a) Would be impossible to implement on Windows because of sheer architectural differences (eg: mknod). (b) Already optional (augeas, inotify). (c) Not currently optional but not implemented on older RHEL and Debian releases (ntfs-3g.probe, scrub, zerofree). The optional groups I've defined according to these criteria are: . augeas . inotify . linuxfsuuid . linuxmodules . linuxxattrs . lvm2 . mknod . ntfs3g . scrub . selinux . zerofree (Note that these choices don't prevent us from adding more optional groups in future. On the other hand to avoid breaking ABIs we would not wish to change the above groups). The rest of this large commit is really just implementation: Each optional function is classified using Optional "group" flag in the generator. The daemon has to implement a function int optgroup_<name>_available (void); for each optional group. Some of these functions are fixed at compile time, and some do simple run-time tests. The do_available implementation in the daemon looks up the correct function in a table and runs it. We document the optional groups in the guestfs(3) man page. Also: I added a NOT_AVAILABLE macro in order to unify all the existing places where we had a message equivalent to "function __func__ is not available".
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/augeas.c52
-rw-r--r--daemon/available.c23
-rw-r--r--daemon/configure.ac24
-rw-r--r--daemon/daemon.h17
-rw-r--r--daemon/inotify.c31
-rw-r--r--daemon/lvm.c8
-rw-r--r--daemon/mknod.c18
-rw-r--r--daemon/modprobe.c8
-rw-r--r--daemon/ntfs.c8
-rw-r--r--daemon/scrub.c8
-rw-r--r--daemon/selinux.c21
-rw-r--r--daemon/swap.c19
-rw-r--r--daemon/xattr.c47
-rw-r--r--daemon/zerofree.c8
15 files changed, 214 insertions, 80 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index d851e527..9fa8ddab 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -81,6 +81,8 @@ guestfsd_SOURCES = \
mount.c \
names.c \
ntfs.c \
+ optgroups.c \
+ optgroups.h \
parted.c \
pingdaemon.c \
proto.c \
diff --git a/daemon/augeas.c b/daemon/augeas.c
index b56012cd..be53d294 100644
--- a/daemon/augeas.c
+++ b/daemon/augeas.c
@@ -29,6 +29,7 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#ifdef HAVE_AUGEAS
/* The Augeas handle. We maintain a single handle per daemon, which
@@ -45,6 +46,18 @@ static augeas *aug = NULL;
} \
} \
while (0)
+
+int
+optgroup_augeas_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_AUGEAS */
+int
+optgroup_augeas_available (void)
+{
+ return 0;
+}
#endif
/* We need to rewrite the root path so it is based at /sysroot. */
@@ -75,8 +88,7 @@ do_aug_init (const char *root, int flags)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -91,8 +103,7 @@ do_aug_close (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -111,8 +122,7 @@ do_aug_defvar (const char *name, const char *expr)
}
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -133,8 +143,7 @@ do_aug_defnode (const char *name, const char *expr, const char *val)
r.b = created;
return &r;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -176,8 +185,7 @@ do_aug_get (const char *path)
return v; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -197,8 +205,7 @@ do_aug_set (const char *path, const char *val)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -218,8 +225,7 @@ do_aug_insert (const char *path, const char *label, int before)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -239,8 +245,7 @@ do_aug_rm (const char *path)
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -260,8 +265,7 @@ do_aug_mv (const char *src, const char *dest)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -295,8 +299,7 @@ do_aug_match (const char *path)
return matches; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -313,8 +316,7 @@ do_aug_save (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -331,8 +333,7 @@ do_aug_load (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -379,7 +380,6 @@ do_aug_ls (const char *path)
sort_strings (matches, count_strings ((void *) matches));
return matches; /* Caller frees. */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/available.c b/daemon/available.c
index b43d1820..77fdfa2c 100644
--- a/daemon/available.c
+++ b/daemon/available.c
@@ -29,9 +29,26 @@
int
do_available (char *const *groups)
{
- if (groups[0] != NULL) {
- reply_with_error ("%s: unknown group", groups[0]);
- return -1;
+ int av;
+ size_t i, j;
+
+ for (i = 0; groups[i] != NULL; ++i) {
+ for (j = 0; optgroups[j].group != NULL; ++j) {
+ if (STREQ (groups[i], optgroups[j].group)) {
+ av = optgroups[j].available ();
+ if (!av) {
+ reply_with_error ("%s: group not available", optgroups[j].group);
+ return -1;
+ }
+ break; /* out of for (j) loop */
+ }
+ }
+
+ /* Unknown group? */
+ if (optgroups[j].group == NULL) {
+ reply_with_error ("%s: unknown group", groups[i]);
+ return -1;
+ }
}
return 0;
diff --git a/daemon/configure.ac b/daemon/configure.ac
index a1f54a3b..c6d9d98f 100644
--- a/daemon/configure.ac
+++ b/daemon/configure.ac
@@ -133,7 +133,7 @@ AC_STRUCT_DIRENT_D_TYPE
dnl Check if stat has the required fields.
AC_STRUCT_ST_BLOCKS
AC_CHECK_MEMBER([struct stat.st_blksize],[
- AC_DEFINE([HAVE_STRUCT_STAT_ST_BLKSIZE],[1],[Define to 1 if 'st_blksize' is a member of 'struct stat'])])
+ AC_DEFINE([HAVE_STRUCT_STAT_ST_BLKSIZE],[1],[Define to 1 if 'st_blksize' is a member of 'struct stat'])])
dnl Check for Augeas (now optional).
AC_CHECK_LIB([augeas],[aug_match],[
@@ -164,17 +164,17 @@ AC_CHECK_LIB([portablexdr],[xdrmem_create],[],[
dnl Functions which may not be available in older distributions.
AC_CHECK_FUNCS([\
- futimens \
- getxattr \
- inotify_init1 \
- lgetxattr \
- listxattr \
- llistxattr \
- lsetxattr \
- lremovexattr \
- mknod \
- removexattr \
- setxattr])
+ futimens \
+ getxattr \
+ inotify_init1 \
+ lgetxattr \
+ listxattr \
+ llistxattr \
+ lsetxattr \
+ lremovexattr \
+ mknod \
+ removexattr \
+ setxattr])
dnl Headers.
AC_CHECK_HEADERS([\
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 120c86cc..7ba75990 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -105,6 +105,13 @@ extern guestfs_int_lvm_lv_list *parse_command_line_lvs (void);
/*-- in proto.c --*/
extern void main_loop (int sock) __attribute__((noreturn));
+/*-- in optgroups.c (auto-generated) --*/
+struct optgroup {
+ const char *group; /* Name of the optional group. */
+ int (*available) (void); /* Function to test availability. */
+};
+extern struct optgroup optgroups[];
+
/* ordinary daemon functions use these to indicate errors */
extern void reply_with_error (const char *fs, ...)
__attribute__((format (printf,1,2)));
@@ -225,6 +232,16 @@ extern void reply (xdrproc_t xdrp, char *ret);
} \
while (0)
+/* Marks functions which are not available.
+ * NB. Cannot be used for FileIn functions.
+ */
+#define NOT_AVAILABLE(errcode) \
+ do { \
+ reply_with_error ("%s: function not available", __func__); \
+ return (errcode); \
+ } \
+ while (0)
+
#ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x) /* empty */
diff --git a/daemon/inotify.c b/daemon/inotify.c
index 465d0b6e..24ce76e2 100644
--- a/daemon/inotify.c
+++ b/daemon/inotify.c
@@ -31,6 +31,7 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#ifdef HAVE_SYS_INOTIFY_H
/* Currently open inotify handle, or -1 if not opened. */
@@ -38,6 +39,18 @@ static int inotify_fd = -1;
static char inotify_buf[64*1024*1024]; /* Event buffer, [0..posn-1] is valid */
static size_t inotify_posn = 0;
+
+int
+optgroup_inotify_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_SYS_INOTIFY_H */
+int
+optgroup_inotify_available (void)
+{
+ return 0;
+}
#endif
/* Because inotify_init does NEED_ROOT, NEED_INOTIFY implies NEED_ROOT. */
@@ -106,8 +119,7 @@ do_inotify_init (int max_events)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -132,8 +144,7 @@ do_inotify_close (void)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -161,8 +172,7 @@ do_inotify_add_watch (const char *path, int mask)
return r;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -179,8 +189,7 @@ do_inotify_rm_watch (int wd)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -294,8 +303,7 @@ do_inotify_read (void)
free (ret);
return NULL;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
@@ -371,7 +379,6 @@ do_inotify_files (void)
unlink ("/tmp/inotify");
return NULL;
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 3920e95b..564517c5 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "c-ctype.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_lvm2_available (void)
+{
+ int r = access ("/sbin/lvm", X_OK);
+ return r == 0;
+}
/* LVM actions. Keep an eye on liblvm, although at the time
* of writing it hasn't progressed very far.
diff --git a/daemon/mknod.c b/daemon/mknod.c
index 6ff88efa..46a18392 100644
--- a/daemon/mknod.c
+++ b/daemon/mknod.c
@@ -29,6 +29,21 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+#ifdef HAVE_MKNOD
+int
+optgroup_mknod_available (void)
+{
+ return 1;
+}
+#else
+int
+optgroup_mknod_available (void)
+{
+ return 0;
+}
+#endif
int
do_mknod (int mode, int devmajor, int devminor, const char *path)
@@ -47,8 +62,7 @@ do_mknod (int mode, int devmajor, int devminor, const char *path)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
diff --git a/daemon/modprobe.c b/daemon/modprobe.c
index 7e3d1b70..ac62b349 100644
--- a/daemon/modprobe.c
+++ b/daemon/modprobe.c
@@ -23,6 +23,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_linuxmodules_available (void)
+{
+ int r = access ("/sbin/modprobe", X_OK);
+ return r == 0;
+}
int
do_modprobe (const char *module)
diff --git a/daemon/ntfs.c b/daemon/ntfs.c
index 85deb654..b3530084 100644
--- a/daemon/ntfs.c
+++ b/daemon/ntfs.c
@@ -25,6 +25,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_ntfs3g_available (void)
+{
+ int r = access ("/bin/ntfs-3g.probe", X_OK);
+ return r == 0;
+}
int
do_ntfs_3g_probe (int rw, const char *device)
diff --git a/daemon/scrub.c b/daemon/scrub.c
index 15c8b6c2..e37a1e11 100644
--- a/daemon/scrub.c
+++ b/daemon/scrub.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_scrub_available (void)
+{
+ int r = access ("/usr/bin/scrub", X_OK);
+ return r == 0;
+}
int
do_scrub_device (const char *device)
diff --git a/daemon/selinux.c b/daemon/selinux.c
index 3b4b9ba6..e49e657b 100644
--- a/daemon/selinux.c
+++ b/daemon/selinux.c
@@ -29,6 +29,21 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+#if defined(HAVE_LIBSELINUX)
+int
+optgroup_selinux_available (void)
+{
+ return 1;
+}
+#else /* !HAVE_LIBSELINUX */
+int
+optgroup_selinux_available (void)
+{
+ return 0;
+}
+#endif /* !HAVE_LIBSELINUX */
/* setcon is only valid under the following circumstances:
* - single threaded
@@ -45,8 +60,7 @@ do_setcon (const char *context)
return 0;
#else
- reply_with_error ("%s is not available", __func__);
- return -1;
+ NOT_AVAILABLE (-1);
#endif
}
@@ -71,7 +85,6 @@ do_getcon (void)
return r; /* caller frees */
#else
- reply_with_error ("%s is not available", __func__);
- return NULL;
+ NOT_AVAILABLE (NULL);
#endif
}
diff --git a/daemon/swap.c b/daemon/swap.c
index bcc5f1b1..2d3d9ff4 100644
--- a/daemon/swap.c
+++ b/daemon/swap.c
@@ -26,6 +26,25 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+/* Convenient place to test for the later version of e2fsprogs
+ * and util-linux which supports -U parameters to specify UUIDs.
+ * (Not supported in RHEL 5).
+ */
+int
+optgroup_linuxfsuuid_available (void)
+{
+ char *err;
+ int av;
+
+ /* Ignore return code - mkswap --help *will* fail. */
+ command (NULL, &err, "/sbin/mkswap", "--help", NULL);
+
+ av = strstr (err, "-U") != NULL;
+ free (err);
+ return av;
+}
static int
mkswap (const char *device, const char *flag, const char *value)
diff --git a/daemon/xattr.c b/daemon/xattr.c
index c218dea1..e58dc7ea 100644
--- a/daemon/xattr.c
+++ b/daemon/xattr.c
@@ -24,16 +24,23 @@
#include "../src/guestfs_protocol.h"
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
#if defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
-#ifdef HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#else
-#ifdef HAVE_SYS_XATTR_H
-#include <sys/xattr.h>
-#endif
-#endif
+# ifdef HAVE_ATTR_XATTR_H
+# include <attr/xattr.h>
+# else
+# ifdef HAVE_SYS_XATTR_H
+# include <sys/xattr.h>
+# endif
+# endif
+
+int
+optgroup_linuxxattrs_available (void)
+{
+ return 1;
+}
static guestfs_int_xattr_list *getxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size));
static int _setxattr (const char *xattr, const char *val, int vallen, const char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags));
@@ -442,54 +449,52 @@ do_lxattrlist (const char *path, char *const *names)
}
#else /* no xattr.h */
+int
+optgroup_linuxxattrs_available (void)
+{
+ return 0;
+}
guestfs_int_xattr_list *
do_getxattrs (const char *path)
{
- reply_with_error ("getxattrs: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
guestfs_int_xattr_list *
do_lgetxattrs (const char *path)
{
- reply_with_error ("lgetxattrs: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
int
do_setxattr (const char *xattr, const char *val, int vallen, const char *path)
{
- reply_with_error ("setxattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path)
{
- reply_with_error ("lsetxattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_removexattr (const char *xattr, const char *path)
{
- reply_with_error ("removexattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
int
do_lremovexattr (const char *xattr, const char *path)
{
- reply_with_error ("lremovexattr: no support for xattrs");
- return -1;
+ NOT_AVAILABLE (-1);
}
guestfs_int_xattr_list *
do_lxattrlist (const char *path, char *const *names)
{
- reply_with_error ("lxattrlist: no support for xattrs");
- return NULL;
+ NOT_AVAILABLE (NULL);
}
#endif /* no xattr.h */
diff --git a/daemon/zerofree.c b/daemon/zerofree.c
index ffb9b70b..05a547bd 100644
--- a/daemon/zerofree.c
+++ b/daemon/zerofree.c
@@ -26,6 +26,14 @@
#include "daemon.h"
#include "actions.h"
+#include "optgroups.h"
+
+int
+optgroup_zerofree_available (void)
+{
+ int r = access ("/usr/sbin/zerofree", X_OK);
+ return r == 0;
+}
int
do_zerofree (const char *device)