From 7d2ae9f30f814116c0db8fecda1eb7d412e8ee58 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 10 Dec 2012 16:18:39 +0000 Subject: [PATCH] daemon: Generate the code when libraries are statically not available. Since we as developers rarely test the case where some library is statically not available, that side of the code was hardly tested, except by unfortunate users in the field who often hit cases where functions were missing or misdeclared. In fact, when making this change I noticed several bugs like that. Change it so that this code is autogenerated, and therefore always correct and up to date. Previous code which looked like this: int optgroup_acl_available (void) { return 0; } char * __attribute__((noreturn)) do_acl_get_file (const char *path, const char *acltype) { abort (); } /* etc */ is replaced by a single line: OPTGROUP_ACL_NOT_AVAILABLE --- daemon/acl.c | 28 +----------- daemon/augeas.c | 94 +-------------------------------------- daemon/cap.c | 22 +-------- daemon/hivex.c | 106 +------------------------------------------- daemon/inotify.c | 46 +------------------ daemon/mknod.c | 30 +------------ daemon/realpath.c | 12 +---- daemon/selinux.c | 18 +------- daemon/xattr.c | 64 +------------------------- generator/c.ml | 2 + generator/daemon.ml | 31 +++++++++++++ 11 files changed, 42 insertions(+), 411 deletions(-) diff --git a/daemon/acl.c b/daemon/acl.c index f906dcbee..fcb14e186 100644 --- a/daemon/acl.c +++ b/daemon/acl.c @@ -144,32 +144,6 @@ do_acl_delete_def_file (const char *dir) #else /* no acl library */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because - * optgroup_acl_available returns false. - */ -int -optgroup_acl_available (void) -{ - return 0; -} - -char * __attribute__((noreturn)) -do_acl_get_file (const char *path, const char *acltype) -{ - abort (); -} - -int __attribute__((noreturn)) -do_acl_set_file (const char *path, const char *acltype, const char *acl) -{ - abort (); -} - -int __attribute__((noreturn)) -do_acl_delete_def_file (const char *dir) -{ - abort (); -} +OPTGROUP_ACL_NOT_AVAILABLE #endif /* no acl library */ diff --git a/daemon/augeas.c b/daemon/augeas.c index a6495d267..0de8369ac 100644 --- a/daemon/augeas.c +++ b/daemon/augeas.c @@ -379,98 +379,6 @@ do_aug_ls (const char *path) #else /* !HAVE_AUGEAS */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because optgroup_augeas_available - * returns false. - */ -int -optgroup_augeas_available (void) -{ - return 0; -} - -int __attribute__((noreturn)) -do_aug_init (const char *root, int flags) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_close (void) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_defvar (const char *name, const char *expr) -{ - abort (); -} - -guestfs_int_int_bool * __attribute__((noreturn)) -do_aug_defnode (const char *name, const char *expr, const char *val) -{ - abort (); -} - -char * __attribute__((noreturn)) -do_aug_get (const char *path) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_set (const char *path, const char *val) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_clear (const char *path) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_insert (const char *path, const char *label, int before) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_rm (const char *path) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_mv (const char *src, const char *dest) -{ - abort (); -} - -char ** __attribute__((noreturn)) -do_aug_match (const char *path) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_save (void) -{ - abort (); -} - -int __attribute__((noreturn)) -do_aug_load (void) -{ - abort (); -} - -char ** __attribute__((noreturn)) -do_aug_ls (const char *path) -{ - abort (); -} +OPTGROUP_AUGEAS_NOT_AVAILABLE #endif diff --git a/daemon/cap.c b/daemon/cap.c index cddc12a2f..d1f03989b 100644 --- a/daemon/cap.c +++ b/daemon/cap.c @@ -106,26 +106,6 @@ do_cap_set_file (const char *path, const char *capstr) #else /* no libcap */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because - * optgroup_linuxcaps_available returns false. - */ -int -optgroup_linuxcaps_available (void) -{ - return 0; -} - -char * __attribute__((noreturn)) -do_cap_get_file (const char *path) -{ - abort (); -} - -int __attribute__((noreturn)) -do_cap_set_file (const char *path, const char *cap) -{ - abort (); -} +OPTGROUP_LINUXCAPS_NOT_AVAILABLE #endif /* no libcap */ diff --git a/daemon/hivex.c b/daemon/hivex.c index f13d3d7ea..27a9c5c80 100644 --- a/daemon/hivex.c +++ b/daemon/hivex.c @@ -400,110 +400,6 @@ do_hivex_node_set_value (int64_t nodeh, #else /* !HAVE_HIVEX */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because optgroup_hivex_available - * returns false. - */ -int -optgroup_hivex_available (void) -{ - return 0; -} - -int __attribute__((noreturn)) -do_hivex_open (const char *filename, int verbose, int debug, int write) -{ - abort (); -} - -int __attribute__((noreturn)) -do_hivex_close (void) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_root (void) -{ - abort (); -} - -char * __attribute__((noreturn)) -do_hivex_node_name (int64_t nodeh) -{ - abort (); -} - -guestfs_int_hivex_node_list * __attribute__((noreturn)) -do_hivex_node_children (int64_t nodeh) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_node_get_child (int64_t nodeh, const char *name) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_node_parent (int64_t nodeh) -{ - abort (); -} - -guestfs_int_hivex_value_list * __attribute__((noreturn)) -do_hivex_node_values (int64_t nodeh) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_node_get_value (int64_t nodeh, const char *key) -{ - abort (); -} - -char * __attribute__((noreturn)) -do_hivex_value_key (int64_t valueh) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_value_type (int64_t valueh) -{ - abort (); -} - -char * __attribute__((noreturn)) -do_hivex_value_value (int64_t valueh, size_t *size_r) -{ - abort (); -} - -int __attribute__((noreturn)) -do_hivex_commit (const char *filename) -{ - abort (); -} - -int64_t __attribute__((noreturn)) -do_hivex_node_add_child (int64_t parent, const char *name) -{ - abort (); -} - -int __attribute__((noreturn)) -do_hivex_node_delete_child (int64_t nodeh) -{ - abort (); -} - -int __attribute__((noreturn)) -do_hivex_node_set_value (int64_t nodeh, const char *key, int64_t t, const char *val, size_t val_size) -{ - abort (); -} +OPTGROUP_HIVEX_NOT_AVAILABLE #endif /* !HAVE_HIVEX */ diff --git a/daemon/inotify.c b/daemon/inotify.c index cb0a3662d..e299c25d6 100644 --- a/daemon/inotify.c +++ b/daemon/inotify.c @@ -388,50 +388,6 @@ do_inotify_files (void) #else /* !HAVE_SYS_INOTIFY_H */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because optgroup_inotify_available - * returns false. - */ -int -optgroup_inotify_available (void) -{ - return 0; -} - -int -do_inotify_init (int max_events) -{ - abort (); -} - -int -do_inotify_close (void) -{ - abort (); -} - -int64_t -do_inotify_add_watch (const char *path, int mask) -{ - abort (); -} - -int -do_inotify_rm_watch (int wd) -{ - abort (); -} - -guestfs_int_inotify_event_list * -do_inotify_read (void) -{ - abort (); -} - -char ** -do_inotify_files (void) -{ - abort (); -} +OPTGROUP_INOTIFY_NOT_AVAILABLE #endif diff --git a/daemon/mknod.c b/daemon/mknod.c index 6e678fd78..7f7121089 100644 --- a/daemon/mknod.c +++ b/daemon/mknod.c @@ -80,34 +80,6 @@ do_mknod_c (int mode, int devmajor, int devminor, const char *path) #else -int -optgroup_mknod_available (void) -{ - return 0; -} - -int -do_mknod (int mode, int devmajor, int devminor, const char *path) -{ - abort (); -} - -int -do_mkfifo (int mode, const char *path) -{ - abort (); -} - -int -do_mknod_b (int mode, int devmajor, int devminor, const char *path) -{ - abort (); -} - -int -do_mknod_c (int mode, int devmajor, int devminor, const char *path) -{ - abort (); -} +OPTGROUP_MKNOD_NOT_AVAILABLE #endif diff --git a/daemon/realpath.c b/daemon/realpath.c index aae22aeed..64a75c9c8 100644 --- a/daemon/realpath.c +++ b/daemon/realpath.c @@ -64,17 +64,7 @@ do_realpath (const char *path) #else /* !HAVE_REALPATH */ -int -optgroup_realpath_available (void) -{ - return 0; -} - -char * -do_realpath (const char *path) -{ - abort (); -} +OPTGROUP_REALPATH_NOT_AVAILABLE #endif /* !HAVE_REALPATH */ diff --git a/daemon/selinux.c b/daemon/selinux.c index cbf2fc303..1c1446d30 100644 --- a/daemon/selinux.c +++ b/daemon/selinux.c @@ -87,22 +87,6 @@ do_getcon (void) #else /* !HAVE_LIBSELINUX */ -int -optgroup_selinux_available (void) -{ - return 0; -} - -int __attribute__((noreturn)) -do_setcon (const char *context) -{ - abort (); -} - -char * __attribute__((noreturn)) -do_getcon (void) -{ - abort (); -} +OPTGROUP_SELINUX_NOT_AVAILABLE #endif /* !HAVE_LIBSELINUX */ diff --git a/daemon/xattr.c b/daemon/xattr.c index 3c0363e4b..54ebb9ba1 100644 --- a/daemon/xattr.c +++ b/daemon/xattr.c @@ -541,68 +541,6 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r) #else /* no xattr.h */ -/* Note that the wrapper code (daemon/stubs.c) ensures that the - * functions below are never called because - * optgroup_linuxxattrs_available returns false. - */ -int -optgroup_linuxxattrs_available (void) -{ - return 0; -} - -guestfs_int_xattr_list * -do_getxattrs (const char *path) -{ - abort (); -} - -guestfs_int_xattr_list * -do_lgetxattrs (const char *path) -{ - abort (); -} - -int -do_setxattr (const char *xattr, const char *val, int vallen, const char *path) -{ - abort (); -} - -int -do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path) -{ - abort (); -} - -int -do_removexattr (const char *xattr, const char *path) -{ - abort (); -} - -int -do_lremovexattr (const char *xattr, const char *path) -{ - abort (); -} - -guestfs_int_xattr_list * -do_internal_lxattrlist (const char *path, char *const *names) -{ - abort (); -} - -char * -do_getxattr (const char *path, const char *name, size_t *size_r) -{ - abort (); -} - -char * -do_lgetxattr (const char *path, const char *name, size_t *size_r) -{ - abort (); -} +OPTGROUP_LINUXXATTRS_NOT_AVAILABLE #endif /* no xattr.h */ diff --git a/generator/c.ml b/generator/c.ml index 396054552..418ed701a 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -50,6 +50,7 @@ let rec generate_prototype ?(extern = true) ?(static = false) ?(single_line = false) ?(indent = "") ?(newline = false) ?(in_daemon = false) ?(dll_public = false) + ?(attribute_noreturn = false) ?(prefix = "") ?(suffix = "") ?handle ?(optarg_proto = Dots) @@ -82,6 +83,7 @@ let rec generate_prototype ?(extern = true) ?(static = false) else pr "guestfs_int_%s_list *" typ ); if single_line && !space then pr " "; + if attribute_noreturn then pr "__attribute__((noreturn)) "; if not single_line then pr "\n%s" indent; let is_RBufferOut = match ret with RBufferOut _ -> true | _ -> false in pr "%s%s%s (" prefix name suffix; diff --git a/generator/daemon.ml b/generator/daemon.ml index 64b3ac0f7..3c2f949f2 100644 --- a/generator/daemon.ml +++ b/generator/daemon.ml @@ -590,4 +590,35 @@ and generate_daemon_optgroups_h () = ) optgroups; pr "\n"; + + pr "\ +/* These macros can be used to disable an entire group of functions. + * The advantage of generating this code is that it avoids an + * undetected error when a new function in a group is added, but + * the appropriate abort function is not added to the daemon (because + * the developers rarely test that the daemon builds when a library + * is not present). + */ + +"; + List.iter ( + fun (group, fns) -> + pr "#define OPTGROUP_%s_NOT_AVAILABLE \\\n" (String.uppercase group); + List.iter ( + fun { name = name; style = ret, args, optargs } -> + let style = ret, args @ args_of_optargs optargs, [] in + pr " "; + generate_prototype + ~prefix:"do_" + ~attribute_noreturn:true + ~single_line:true ~newline:false + ~extern:false ~in_daemon:true + ~semicolon:false + name style; + pr " { abort (); } \\\n" + ) fns; + pr " int optgroup_%s_available (void) { return 0; }\n" group; + pr "\n" + ) optgroups; + pr "#endif /* GUESTFSD_OPTGROUPS_H */\n"