* Apart from that, long descriptions are just perldoc paragraphs.
*)
-(* Generate a random UUID (used in tests). *)
+(* Generate a uuidgen-compatible UUID (used in tests). However to
+ * avoid having the UUID change every time we rebuild the tests,
+ * generate it as a function of the contents of the
+ * generator.ml file.
+ *
+ * Originally I thought uuidgen was using RFC 4122, but it doesn't
+ * appear to.
+ *
+ * Note that the format must be 01234567-0123-0123-0123-0123456789ab
+ *)
let uuidgen () =
- let chan = open_process_in "uuidgen" in
- let uuid = input_line chan in
- (match close_process_in chan with
- | WEXITED 0 -> ()
- | WEXITED _ ->
- failwith "uuidgen: process exited with non-zero status"
- | WSIGNALED _ | WSTOPPED _ ->
- failwith "uuidgen: process signalled or stopped by signal"
- );
- uuid
+ let s = Digest.to_hex (Digest.file "src/generator.ml") in
+ String.sub s 0 8 ^ "-"
+ ^ String.sub s 8 4 ^ "-"
+ ^ String.sub s 12 4 ^ "-"
+ ^ String.sub s 16 4 ^ "-"
+ ^ String.sub s 20 12
(* These test functions are used in the language binding tests. *)
[["is_file"; "/known-1"]]);
InitISOFS, Always, TestOutputFalse (
[["is_file"; "/directory"]])],
- "test if file exists",
+ "test if a regular file",
"\
-This returns C<true> if and only if there is a file
+This returns C<true> if and only if there is a regular file
with the given C<path> name. Note that it returns false for
other objects like directories.
[["is_dir"; "/known-3"]]);
InitISOFS, Always, TestOutputTrue (
[["is_dir"; "/directory"]])],
- "test if file exists",
+ "test if a directory",
"\
This returns C<true> if and only if there is a directory
with the given C<path> name. Note that it returns false for
| CallBool of bool
| CallBuffer of string
+(* Used for the guestfish -N (prepared disk images) option.
+ * Note that the longdescs are indented by 2 spaces.
+ *)
+let prepopts = [
+ ("disk",
+ "create a blank disk",
+ [ "size", "100M", "the size of the disk image" ],
+ " Create a blank disk, size 100MB (by default).
+
+ The default size can be changed by supplying an optional parameter.");
+
+ ("part",
+ "create a partitioned disk",
+ [ "size", "100M", "the size of the disk image";
+ "partition", "mbr", "partition table type" ],
+ " Create a disk with a single partition. By default the size of the disk
+ is 100MB (the available space in the partition will be a tiny bit smaller)
+ and the partition table will be MBR (old DOS-style).
+
+ These defaults can be changed by supplying optional parameters.");
+
+ ("fs",
+ "create a filesystem",
+ [ "filesystem", "ext2", "the type of filesystem to use";
+ "size", "100M", "the size of the disk image";
+ "partition", "mbr", "partition table type" ],
+ " Create a disk with a single partition, with the partition containing
+ an empty filesystem. This defaults to creating a 100MB disk (the available
+ space in the filesystem will be a tiny bit smaller) with an MBR (old
+ DOS-style) partition table and an ext2 filesystem.
+
+ These defaults can be changed by supplying optional parameters.");
+]
+
(* Used to memoize the result of pod2text. *)
let pod2text_memo_filename = "src/.pod2text.data"
let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
The string is owned by the guest handle and must I<not> be freed.\n\n"
| RConstOptString _ ->
pr "This function returns a string which may be NULL.
-There is way to return an error from this function.
+There is no way to return an error from this function.
The string is owned by the guest handle and must I<not> be freed.\n\n"
| RString _ ->
pr "This function returns a string, or NULL on error.
generate_header CStyle LGPLv2plus;
(* This has to be defined to get around a limitation in Sun's rpcgen. *)
- pr "typedef string str<>;\n";
+ pr "typedef string guestfs_str<>;\n";
pr "\n";
(* Internal structures. *)
function
| Pathname n | Device n | Dev_or_Path n | String n ->
pr " string %s<>;\n" n
- | OptString n -> pr " str *%s;\n" n
- | StringList n | DeviceList n -> pr " str %s<>;\n" n
+ | OptString n -> pr " guestfs_str *%s;\n" n
+ | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n
| Bool n -> pr " bool %s;\n" n
| Int n -> pr " int %s;\n" n
| Int64 n -> pr " hyper %s;\n" n
pr "};\n\n"
| RStringList n ->
pr "struct %s_ret {\n" name;
- pr " str %s<>;\n" n;
+ pr " guestfs_str %s<>;\n" n;
pr "};\n\n"
| RStruct (n, typ) ->
pr "struct %s_ret {\n" name;
pr "};\n\n"
| RHashtable n ->
pr "struct %s_ret {\n" name;
- pr " str %s<>;\n" n;
+ pr " guestfs_str %s<>;\n" n;
pr "};\n\n"
| RBufferOut n ->
pr "struct %s_ret {\n" name;
#include \"guestfs-internal-actions.h\"
#include \"guestfs_protocol.h\"
-#define error guestfs_error
-//#define perrorf guestfs_perrorf
-#define safe_malloc guestfs_safe_malloc
-#define safe_realloc guestfs_safe_realloc
-//#define safe_strdup guestfs_safe_strdup
-#define safe_memdup guestfs_safe_memdup
-
/* Check the return message from a call for validity. */
static int
check_reply_header (guestfs_h *g,
(* run_<action> actions *)
List.iter (
fun (name, style, _, flags, _, _, _) ->
- pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
+ pr "static int run_%s (const char *cmd, size_t argc, char *argv[])\n" name;
pr "{\n";
(match fst style with
| RErr
) all_functions;
(* run_action function *)
- pr "int run_action (const char *cmd, int argc, char *argv[])\n";
+ pr "int run_action (const char *cmd, size_t argc, char *argv[])\n";
pr "{\n";
List.iter (
fun (name, _, _, flags, _, _, _) ->
try Str.matched_group 1 s
with Not_found ->
failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
- "C<" ^ replace_char sub '_' '-' ^ ">"
+ "L</" ^ replace_char sub '_' '-' ^ ">"
) longdesc in
let name = replace_char name '_' '-' in
let alias =
| Some txt -> pr "%s\n\n" txt
) all_functions_sorted
+and generate_fish_prep_options_h () =
+ generate_header CStyle GPLv2plus;
+
+ pr "#ifndef PREPOPTS_H\n";
+ pr "\n";
+
+ pr "\
+struct prep {
+ const char *name; /* eg. \"fs\" */
+
+ size_t nr_params; /* optional parameters */
+ struct prep_param *params;
+
+ const char *shortdesc; /* short description */
+ const char *longdesc; /* long description */
+
+ /* functions to implement it */
+ void (*prelaunch) (const char *filename, prep_data *);
+ void (*postlaunch) (const char *filename, prep_data *, const char *device);
+};
+
+struct prep_param {
+ const char *pname; /* parameter name */
+ const char *pdefault; /* parameter default */
+ const char *pdesc; /* parameter description */
+};
+
+extern const struct prep preps[];
+#define NR_PREPS %d
+
+" (List.length prepopts);
+
+ List.iter (
+ fun (name, shortdesc, args, longdesc) ->
+ pr "\
+extern void prep_prelaunch_%s (const char *filename, prep_data *data);
+extern void prep_postlaunch_%s (const char *filename, prep_data *data, const char *device);
+
+" name name;
+ ) prepopts;
+
+ pr "\n";
+ pr "#endif /* PREPOPTS_H */\n"
+
+and generate_fish_prep_options_c () =
+ generate_header CStyle GPLv2plus;
+
+ pr "\
+#include \"fish.h\"
+#include \"prepopts.h\"
+
+";
+
+ List.iter (
+ fun (name, shortdesc, args, longdesc) ->
+ pr "static struct prep_param %s_args[] = {\n" name;
+ List.iter (
+ fun (n, default, desc) ->
+ pr " { \"%s\", \"%s\", \"%s\" },\n" n default desc
+ ) args;
+ pr "};\n";
+ pr "\n";
+ ) prepopts;
+
+ pr "const struct prep preps[] = {\n";
+ List.iter (
+ fun (name, shortdesc, args, longdesc) ->
+ pr " { \"%s\", %d, %s_args,
+ \"%s\",
+ \"%s\",
+ prep_prelaunch_%s, prep_postlaunch_%s },
+"
+ name (List.length args) name
+ (c_quote shortdesc) (c_quote longdesc)
+ name name;
+ ) prepopts;
+ pr "};\n"
+
(* Generate a C function prototype. *)
and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
?(single_line = false) ?(newline = false) ?(in_daemon = false)
pr " char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
| OptString n ->
pr " char *%s =\n" n;
- pr " %sv != Val_int (0) ?" n;
+ pr " %sv != Val_int (0) ?\n" n;
pr " guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
| BufferIn n ->
pr " size_t %s_size = caml_string_length (%sv);\n" n n;
| Int64 n -> pr " int64_t %s;\n" n
) (snd style);
- let do_cleanups () =
- List.iter (
- function
- | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
- | Bool _ | Int _ | Int64 _
- | FileIn _ | FileOut _
- | BufferIn _ -> ()
- | StringList n | DeviceList n -> pr " free (%s);\n" n
- ) (snd style)
- in
-
- (* Code. *)
+ (* PREINIT section (local variable declarations). *)
+ pr "PREINIT:\n";
(match fst style with
| RErr ->
- pr "PREINIT:\n";
pr " int r;\n";
+ | RInt _
+ | RBool _ ->
+ pr " int r;\n";
+ | RInt64 _ ->
+ pr " int64_t r;\n";
+ | RConstString _ ->
+ pr " const char *r;\n";
+ | RConstOptString _ ->
+ pr " const char *r;\n";
+ | RString _ ->
+ pr " char *r;\n";
+ | RStringList _ | RHashtable _ ->
+ pr " char **r;\n";
+ pr " size_t i, n;\n";
+ | RStruct (_, typ) ->
+ pr " struct guestfs_%s *r;\n" typ;
+ | RStructList (_, typ) ->
+ pr " struct guestfs_%s_list *r;\n" typ;
+ pr " size_t i;\n";
+ pr " HV *hv;\n";
+ | RBufferOut _ ->
+ pr " char *r;\n";
+ pr " size_t size;\n";
+ );
+
+ (* CODE or PPCODE section. PPCODE is used where we are
+ * returning void, or where we push the return value on the stack
+ * ourselves. Using CODE means we will manipulate RETVAL.
+ *)
+ (match fst style with
+ | RErr ->
pr " PPCODE:\n";
- pr " r = guestfs_%s " name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
+ | RInt n
+ | RBool n ->
+ pr " CODE:\n";
+ | RInt64 n ->
+ pr " CODE:\n";
+ | RConstString n ->
+ pr " CODE:\n";
+ | RConstOptString n ->
+ pr " CODE:\n";
+ | RString n ->
+ pr " CODE:\n";
+ | RStringList n | RHashtable n ->
+ pr " PPCODE:\n";
+ | RBufferOut n ->
+ pr " CODE:\n";
+ | RStruct _
+ | RStructList _ ->
+ pr " PPCODE:\n";
+ );
+
+ (* The call to the C function. *)
+ pr " r = guestfs_%s " name;
+ generate_c_call_args ~handle:"g" style;
+ pr ";\n";
+
+ (* Cleanup any arguments. *)
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
+ | Bool _ | Int _ | Int64 _
+ | FileIn _ | FileOut _
+ | BufferIn _ -> ()
+ | StringList n | DeviceList n -> pr " free (%s);\n" n
+ ) (snd style);
+
+ (* Check return value for errors and return it if necessary. *)
+ (match fst style with
+ | RErr ->
pr " if (r == -1)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
| RInt n
| RBool n ->
- pr "PREINIT:\n";
- pr " int %s;\n" n;
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == -1)\n" n;
+ pr " if (r == -1)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = newSViv (%s);\n" n;
+ pr " RETVAL = newSViv (r);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
| RInt64 n ->
- pr "PREINIT:\n";
- pr " int64_t %s;\n" n;
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == -1)\n" n;
+ pr " if (r == -1)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = my_newSVll (%s);\n" n;
+ pr " RETVAL = my_newSVll (r);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
| RConstString n ->
- pr "PREINIT:\n";
- pr " const char *%s;\n" n;
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = newSVpv (%s, 0);\n" n;
+ pr " RETVAL = newSVpv (r, 0);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
| RConstOptString n ->
- pr "PREINIT:\n";
- pr " const char *%s;\n" n;
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " if (r == NULL)\n";
pr " RETVAL = &PL_sv_undef;\n";
pr " else\n";
- pr " RETVAL = newSVpv (%s, 0);\n" n;
+ pr " RETVAL = newSVpv (r, 0);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
| RString n ->
- pr "PREINIT:\n";
- pr " char *%s;\n" n;
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = newSVpv (%s, 0);\n" n;
- pr " free (%s);\n" n;
+ pr " RETVAL = newSVpv (r, 0);\n";
+ pr " free (r);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
| RStringList n | RHashtable n ->
- pr "PREINIT:\n";
- pr " char **%s;\n" n;
- pr " size_t i, n;\n";
- pr " PPCODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
+ pr " for (n = 0; r[n] != NULL; ++n) /**/;\n";
pr " EXTEND (SP, n);\n";
pr " for (i = 0; i < n; ++i) {\n";
- pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
- pr " free (%s[i]);\n" n;
+ pr " PUSHs (sv_2mortal (newSVpv (r[i], 0)));\n";
+ pr " free (r[i]);\n";
pr " }\n";
- pr " free (%s);\n" n;
+ pr " free (r);\n";
| RStruct (n, typ) ->
let cols = cols_of_struct typ in
- generate_perl_struct_code typ cols name style n do_cleanups
+ generate_perl_struct_code typ cols name style n
| RStructList (n, typ) ->
let cols = cols_of_struct typ in
- generate_perl_struct_list_code typ cols name style n do_cleanups
+ generate_perl_struct_list_code typ cols name style n
| RBufferOut n ->
- pr "PREINIT:\n";
- pr " char *%s;\n" n;
- pr " size_t size;\n";
- pr " CODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = newSVpvn (%s, size);\n" n;
- pr " free (%s);\n" n;
+ pr " RETVAL = newSVpvn (r, size);\n";
+ pr " free (r);\n";
pr " OUTPUT:\n";
pr " RETVAL\n"
);
pr "\n"
) all_functions
-and generate_perl_struct_list_code typ cols name style n do_cleanups =
- pr "PREINIT:\n";
- pr " struct guestfs_%s_list *%s;\n" typ n;
- pr " size_t i;\n";
- pr " HV *hv;\n";
- pr " PPCODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+and generate_perl_struct_list_code typ cols name style n =
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " EXTEND (SP, %s->len);\n" n;
- pr " for (i = 0; i < %s->len; ++i) {\n" n;
+ pr " EXTEND (SP, r->len);\n";
+ pr " for (i = 0; i < r->len; ++i) {\n";
pr " hv = newHV ();\n";
List.iter (
function
| name, FString ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVpv (r->val[i].%s, 0), 0);\n"
+ name (String.length name) name
| name, FUUID ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVpv (r->val[i].%s, 32), 0);\n"
+ name (String.length name) name
| name, FBuffer ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
- name (String.length name) n name n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (r->val[i].%s, r->val[i].%s_len), 0);\n"
+ name (String.length name) name name
| name, (FBytes|FUInt64) ->
- pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (r->val[i].%s), 0);\n"
+ name (String.length name) name
| name, FInt64 ->
- pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (r->val[i].%s), 0);\n"
+ name (String.length name) name
| name, (FInt32|FUInt32) ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVnv (r->val[i].%s), 0);\n"
+ name (String.length name) name
| name, FChar ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&r->val[i].%s, 1), 0);\n"
+ name (String.length name) name
| name, FOptPercent ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
- name (String.length name) n name
+ pr " (void) hv_store (hv, \"%s\", %d, newSVnv (r->val[i].%s), 0);\n"
+ name (String.length name) name
) cols;
pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
pr " }\n";
- pr " guestfs_free_%s_list (%s);\n" typ n
-
-and generate_perl_struct_code typ cols name style n do_cleanups =
- pr "PREINIT:\n";
- pr " struct guestfs_%s *%s;\n" typ n;
- pr " PPCODE:\n";
- pr " %s = guestfs_%s " n name;
- generate_c_call_args ~handle:"g" style;
- pr ";\n";
- do_cleanups ();
- pr " if (%s == NULL)\n" n;
+ pr " guestfs_free_%s_list (r);\n" typ
+
+and generate_perl_struct_code typ cols name style n =
+ pr " if (r == NULL)\n";
pr " croak (\"%%s\", guestfs_last_error (g));\n";
pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
List.iter (
match col with
| name, FString ->
- pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
- n name
+ pr " PUSHs (sv_2mortal (newSVpv (r->%s, 0)));\n"
+ name
| name, FBuffer ->
- pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
- n name n name
+ pr " PUSHs (sv_2mortal (newSVpvn (r->%s, r->%s_len)));\n"
+ name name
| name, FUUID ->
- pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
- n name
+ pr " PUSHs (sv_2mortal (newSVpv (r->%s, 32)));\n"
+ name
| name, (FBytes|FUInt64) ->
- pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
- n name
+ pr " PUSHs (sv_2mortal (my_newSVull (r->%s)));\n"
+ name
| name, FInt64 ->
- pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
- n name
+ pr " PUSHs (sv_2mortal (my_newSVll (r->%s)));\n"
+ name
| name, (FInt32|FUInt32) ->
- pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
- n name
+ pr " PUSHs (sv_2mortal (newSVnv (r->%s)));\n"
+ name
| name, FChar ->
- pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
- n name
+ pr " PUSHs (sv_2mortal (newSVpv (&r->%s, 1)));\n"
+ name
| name, FOptPercent ->
- pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
- n name
+ pr " PUSHs (sv_2mortal (newSVnv (r->%s)));\n"
+ name
) cols;
- pr " free (%s);\n" n
+ pr " free (r);\n"
(* Generate Sys/Guestfs.pm. *)
and generate_perl_pm () =
=back
+=head1 AVAILABILITY
+
+From time to time we add new libguestfs APIs. Also some libguestfs
+APIs won't be available in all builds of libguestfs (the Fedora
+build is full-featured, but other builds may disable features).
+How do you test whether the APIs that your Perl program needs are
+available in the version of C<Sys::Guestfs> that you are using?
+
+To test if a particular function is available in the C<Sys::Guestfs>
+class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
+(see L<perlobj(1)>). For example:
+
+ use Sys::Guestfs;
+ if (defined (Sys::Guestfs->can (\"set_verbose\"))) {
+ print \"\\$h->set_verbose is available\\n\";
+ }
+
+To test if particular features are supported by the current
+build, use the L</available> method like the example below. Note
+that the appliance must be launched first.
+
+ $h->available ( [\"augeas\"] );
+
+Since the L</available> method croaks if the feature is not supported,
+you might also want to wrap this in an eval and return a boolean.
+In fact this has already been done for you: use
+L<Sys::Guestfs::Lib(3)/feature_available>.
+
+For further discussion on this topic, refer to
+L<guestfs(3)/AVAILABILITY>.
+
+=head1 STORING DATA IN THE HANDLE
+
+The handle returned from L</new> is a hash reference. The hash
+normally contains a single element:
+
+ {
+ _g => [private data used by libguestfs]
+ }
+
+Callers can add other elements to this hash to store data for their own
+purposes. The data lasts for the lifetime of the handle.
+
+Any fields whose names begin with an underscore are reserved
+for private use by libguestfs. We may add more in future.
+
+It is recommended that callers prefix the name of their field(s)
+with some unique string, to avoid conflicts with other users.
+
=head1 COPYRIGHT
Copyright (C) %s Red Hat Inc.
output_to "fish/cmds.c" generate_fish_cmds;
output_to "fish/completion.c" generate_fish_completion;
output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
+ output_to "fish/prepopts.c" generate_fish_prep_options_c;
+ output_to "fish/prepopts.h" generate_fish_prep_options_h;
output_to "ocaml/guestfs.mli" generate_ocaml_mli;
output_to "ocaml/guestfs.ml" generate_ocaml_ml;
output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;