pr "This function takes a key or passphrase parameter which
could contain sensitive material. Read the section
L</KEYS AND PASSPHRASES> for more information.\n\n";
- (match deprecation_notice flags with
+ (match deprecation_notice ~prefix:"guestfs_" flags with
| None -> ()
| Some txt -> pr "%s\n\n" txt
);
extern \"C\" {
#endif
+#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
/* The handle. */
-#ifndef GUESTFS_TYPEDEF_GUESTFS_H
-#define GUESTFS_TYPEDEF_GUESTFS_H 1
+#ifndef GUESTFS_TYPEDEF_H
+#define GUESTFS_TYPEDEF_H 1
typedef struct guestfs_h guestfs_h;
#endif
#define LIBGUESTFS_HAVE_LAST_ERRNO 1
extern int guestfs_last_errno (guestfs_h *g);
-#ifndef GUESTFS_TYPEDEF_GUESTFS_ERROR_HANDLER_CB
-#define GUESTFS_TYPEDEF_GUESTFS_ERROR_HANDLER_CB 1
+#ifndef GUESTFS_TYPEDEF_ERROR_HANDLER_CB
+#define GUESTFS_TYPEDEF_ERROR_HANDLER_CB 1
typedef void (*guestfs_error_handler_cb) (guestfs_h *g, void *opaque, const char *msg);
#endif
-#ifndef GUESTFS_TYPEDEF_GUESTFS_ABORT_CB
-#define GUESTFS_TYPEDEF_GUESTFS_ABORT_CB 1
+#ifndef GUESTFS_TYPEDEF_ABORT_CB
+#define GUESTFS_TYPEDEF_ABORT_CB 1
typedef void (*guestfs_abort_cb) (void) __attribute__((__noreturn__));
#endif
extern guestfs_abort_cb guestfs_get_out_of_memory_handler (guestfs_h *g);
/* Events. */
-#ifndef GUESTFS_TYPEDEF_GUESTFS_LOG_MESSAGE_CB
-#define GUESTFS_TYPEDEF_GUESTFS_LOG_MESSAGE_CB 1
+#ifndef GUESTFS_TYPEDEF_LOG_MESSAGE_CB
+#define GUESTFS_TYPEDEF_LOG_MESSAGE_CB 1
typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *opaque, char *buf, int len);
#endif
-#ifndef GUESTFS_TYPEDEF_GUESTFS_SUBPROCESS_QUIT_CB
-#define GUESTFS_TYPEDEF_GUESTFS_SUBPROCESS_QUIT_CB 1
+#ifndef GUESTFS_TYPEDEF_SUBPROCESS_QUIT_CB
+#define GUESTFS_TYPEDEF_SUBPROCESS_QUIT_CB 1
typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *opaque);
#endif
-#ifndef GUESTFS_TYPEDEF_GUESTFS_LAUNCH_DONE_CB
-#define GUESTFS_TYPEDEF_GUESTFS_LAUNCH_DONE_CB 1
+#ifndef GUESTFS_TYPEDEF_LAUNCH_DONE_CB
+#define GUESTFS_TYPEDEF_LAUNCH_DONE_CB 1
typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *opaque);
#endif
-#ifndef GUESTFS_TYPEDEF_GUESTFS_CLOSE_CB
-#define GUESTFS_TYPEDEF_GUESTFS_CLOSE_CB 1
+#ifndef GUESTFS_TYPEDEF_CLOSE_CB
+#define GUESTFS_TYPEDEF_CLOSE_CB 1
typedef void (*guestfs_close_cb) (guestfs_h *g, void *opaque);
#endif
-#ifndef GUESTFS_TYPEDEF_GUESTFS_PROGRESS_CB
-#define GUESTFS_TYPEDEF_GUESTFS_PROGRESS_CB 1
+#ifndef GUESTFS_TYPEDEF_PROGRESS_CB
+#define GUESTFS_TYPEDEF_PROGRESS_CB 1
typedef void (*guestfs_progress_cb) (guestfs_h *g, void *opaque, int proc_nr, int serial, uint64_t position, uint64_t total);
#endif
let c_type =
match argt with
| Bool n -> "int "
- | Int n -> "int64_t "
- | Int64 n -> "int "
+ | Int n -> "int "
+ | Int64 n -> "int64_t "
| String n -> "const char *"
| _ -> assert false (* checked in generator_checks *) in
let uc_shortname = String.uppercase shortname in
extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes);
extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s);
extern const char *guestfs_tmpdir (void);
+#ifdef GUESTFS_PRIVATE_FOR_EACH_DISK
+extern int guestfs___for_each_disk (guestfs_h *g, virDomainPtr dom, int (*)(guestfs_h *g, const char *filename, const char *format, void *data), void *data);
+#endif
/* End of private functions. */
#ifdef __cplusplus
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include \"guestfs.h\"
#include \"guestfs-internal.h\"
";
- let error_code_of = function
- | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
- | RConstString _ | RConstOptString _
- | RString _ | RStringList _
- | RStruct _ | RStructList _
- | RHashtable _ | RBufferOut _ -> "NULL"
- in
-
(* Generate code to check String-like parameters are not passed in
* as NULL (returning an error if they are).
*)
pr " if (%s == NULL) {\n" n;
pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
pr " \"%s\", \"%s\");\n" shortname n;
- pr " return %s;\n" (error_code_of ret);
+ let errcode =
+ match errcode_of_ret ret with
+ | `CannotReturnError ->
+ if shortname = "test0rconstoptstring" then (* XXX hack *)
+ `ErrorIsNULL
+ else
+ failwithf
+ "%s: RConstOptString function has invalid parameter '%s'"
+ shortname n
+ | (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr_newline := true
pr " optargs->%s == NULL) {\n" n;
pr " error (g, \"%%s: %%s: optional parameter cannot be NULL\",\n";
pr " \"%s\", \"%s\");\n" shortname n;
- pr " return %s;\n" (error_code_of ret);
+ let errcode =
+ match errcode_of_ret ret with
+ | `CannotReturnError -> assert false
+ | (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr_newline := true
pr " if (optargs->bitmask & UINT64_C(0x%Lx)) {\n" mask;
pr " error (g, \"%%s: unknown option in guestfs_%%s_argv->bitmask (this can happen if a program is compiled against a newer version of libguestfs, then dynamically linked to an older version)\",\n";
pr " \"%s\", \"%s\");\n" shortname shortname;
- pr " return %s;\n" (error_code_of ret);
+ let errcode =
+ match errcode_of_ret ret with
+ | `CannotReturnError -> assert false
+ | (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
in
(* Generate code to generate guestfish call traces. *)
let trace_call shortname (ret, args, optargs) =
- pr " if (guestfs__get_trace (g)) {\n";
+ pr " if (trace_flag) {\n";
let needs_i =
List.exists (function
);
) optargs;
- pr " fputc ('\\n', stderr);\n";
pr " }\n";
pr "\n";
in
+ let trace_return ?(indent = 2) (ret, _, _) rv =
+ let indent = spaces indent in
+
+ pr "%sif (trace_flag) {\n" indent;
+
+ let needs_i =
+ match ret with
+ | RStringList _ | RHashtable _ -> true
+ | _ -> false in
+ if needs_i then (
+ pr "%s size_t i;\n" indent;
+ pr "\n"
+ );
+
+ pr "%s fputs (\" = \", stderr);\n" indent;
+ (match ret with
+ | RErr | RInt _ | RBool _ ->
+ pr "%s fprintf (stderr, \"%%d\", %s);\n" indent rv
+ | RInt64 _ ->
+ pr "%s fprintf (stderr, \"%%\" PRIi64, %s);\n" indent rv
+ | RConstString _ | RString _ ->
+ pr "%s fprintf (stderr, \"\\\"%%s\\\"\", %s);\n" indent rv
+ | RConstOptString _ ->
+ pr "%s fprintf (stderr, \"\\\"%%s\\\"\", %s != NULL ? %s : \"NULL\");\n"
+ indent rv rv
+ | RBufferOut _ ->
+ pr "%s guestfs___print_BufferOut (stderr, %s, *size_r);\n" indent rv
+ | RStringList _ | RHashtable _ ->
+ pr "%s fputs (\"[\", stderr);\n" indent;
+ pr "%s for (i = 0; %s[i]; ++i) {\n" indent rv;
+ pr "%s if (i > 0) fputs (\", \", stderr);\n" indent;
+ pr "%s fputs (\"\\\"\", stderr);\n" indent;
+ pr "%s fputs (%s[i], stderr);\n" indent rv;
+ pr "%s fputs (\"\\\"\", stderr);\n" indent;
+ pr "%s }\n" indent;
+ pr "%s fputs (\"]\", stderr);\n" indent;
+ | RStruct (_, typ) ->
+ (* XXX There is code generated for guestfish for printing
+ * these structures. We need to make it generally available
+ * for all callers
+ *)
+ pr "%s fprintf (stderr, \"<struct guestfs_%s *>\");\n"
+ indent typ (* XXX *)
+ | RStructList (_, typ) ->
+ pr "%s fprintf (stderr, \"<struct guestfs_%s_list *>\");\n"
+ indent typ (* XXX *)
+ );
+ pr "%s fputc ('\\n', stderr);\n" indent;
+ pr "%s}\n" indent;
+ pr "\n";
+ in
+
+ let trace_return_error ?(indent = 2) (ret, _, _) =
+ let indent = spaces indent in
+
+ pr "%sif (trace_flag)\n" indent;
+
+ (match ret with
+ | RErr | RInt _ | RBool _
+ | RInt64 _ ->
+ pr "%s fputs (\" = -1 (error)\\n\", stderr);\n" indent
+ | RConstString _ | RString _
+ | RConstOptString _
+ | RBufferOut _
+ | RStringList _ | RHashtable _
+ | RStruct _
+ | RStructList _ ->
+ pr "%s fputs (\" = NULL (error)\\n\", stderr);\n" indent
+ );
+ in
+
(* For non-daemon functions, generate a wrapper around each function. *)
List.iter (
- fun (shortname, (_, _, optargs as style), _, _, _, _, _) ->
+ fun (shortname, (ret, _, optargs as style), _, _, _, _, _) ->
if optargs = [] then
generate_prototype ~extern:false ~semicolon:false ~newline:true
~handle:"g" ~prefix:"guestfs_"
~handle:"g" ~prefix:"guestfs_" ~suffix:"_argv" ~optarg_proto:Argv
shortname style;
pr "{\n";
+ pr " int trace_flag = g->trace;\n";
+ (match ret with
+ | RErr | 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 _ | RBufferOut _ ->
+ pr " char *r;\n"
+ | RStringList _ | RHashtable _ ->
+ pr " char **r;\n"
+ | RStruct (_, typ) ->
+ pr " struct guestfs_%s *r;\n" typ
+ | RStructList (_, typ) ->
+ pr " struct guestfs_%s_list *r;\n" typ
+ );
+ pr "\n";
check_null_strings shortname style;
reject_unknown_optargs shortname style;
trace_call shortname style;
- pr " return guestfs__%s " shortname;
+ pr " r = guestfs__%s " shortname;
generate_c_call_args ~handle:"g" style;
pr ";\n";
+ pr "\n";
+ (match errcode_of_ret ret with
+ | (`ErrorIsMinusOne | `ErrorIsNULL) as errcode ->
+ pr " if (r != %s) {\n" (string_of_errcode errcode);
+ trace_return ~indent:4 style "r";
+ pr " } else {\n";
+ trace_return_error ~indent:4 style;
+ pr " }\n";
+ | `CannotReturnError ->
+ trace_return style "r";
+ );
+ pr "\n";
+ pr " return r;\n";
pr "}\n";
pr "\n"
) non_daemon_functions;
(* Client-side stubs for each function. *)
List.iter (
fun (shortname, (ret, args, optargs as style), _, _, _, _, _) ->
- if optargs <> [] then
- failwithf "optargs not yet implemented for daemon functions";
-
let name = "guestfs_" ^ shortname in
- let error_code = error_code_of ret in
+ let errcode =
+ match errcode_of_ret ret with
+ | `CannotReturnError -> assert false
+ | (`ErrorIsMinusOne | `ErrorIsNULL) as e -> e in
(* Generate the action stub. *)
if optargs = [] then
generate_prototype ~extern:false ~semicolon:false ~newline:true
- ~handle:"g" name style
+ ~handle:"g" ~prefix:"guestfs_" shortname style
else
generate_prototype ~extern:false ~semicolon:false ~newline:true
- ~handle:"g" ~suffix:"_argv" ~optarg_proto:Argv name style;
+ ~handle:"g" ~prefix:"guestfs_" ~suffix:"_argv"
+ ~optarg_proto:Argv shortname style;
pr "{\n";
pr " int serial;\n";
pr " int r;\n";
+ pr " int trace_flag = g->trace;\n";
+ (match ret with
+ | RErr | RInt _ | RBool _ ->
+ pr " int ret_v;\n"
+ | RInt64 _ ->
+ pr " int64_t ret_v;\n"
+ | RConstString _ | RConstOptString _ ->
+ pr " const char *ret_v;\n"
+ | RString _ | RBufferOut _ ->
+ pr " char *ret_v;\n"
+ | RStringList _ | RHashtable _ ->
+ pr " char **ret_v;\n"
+ | RStruct (_, typ) ->
+ pr " struct guestfs_%s *ret_v;\n" typ
+ | RStructList (_, typ) ->
+ pr " struct guestfs_%s_list *ret_v;\n" typ
+ );
+
+ let has_filein =
+ List.exists (function FileIn _ -> true | _ -> false) args in
+ if has_filein then (
+ pr " uint64_t progress_hint = 0;\n";
+ pr " struct stat progress_stat;\n";
+ ) else
+ pr " const uint64_t progress_hint = 0;\n";
+
pr "\n";
check_null_strings shortname style;
reject_unknown_optargs shortname style;
trace_call shortname style;
- pr " if (check_state (g, \"%s\") == -1) return %s;\n"
- shortname error_code;
+
+ (* Calculate the total size of all FileIn arguments to pass
+ * as a progress bar hint.
+ *)
+ List.iter (
+ function
+ | FileIn n ->
+ pr " if (stat (%s, &progress_stat) == 0 &&\n" n;
+ pr " S_ISREG (progress_stat.st_mode))\n";
+ pr " progress_hint += progress_stat.st_size;\n";
+ pr "\n";
+ | _ -> ()
+ ) args;
+
+ (* Check we are in the right state for sending a request. *)
+ pr " if (check_state (g, \"%s\") == -1) {\n" shortname;
+ trace_return_error ~indent:4 style;
+ pr " return %s;\n" (string_of_errcode errcode);
+ pr " }\n";
pr " guestfs___set_busy (g);\n";
pr "\n";
(* Send the main header and arguments. *)
- (match args with
- | [] ->
- pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
- (String.uppercase shortname)
- | args ->
- List.iter (
- function
- | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
- pr " args.%s = (char *) %s;\n" n n
- | OptString n ->
- pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
- | StringList n | DeviceList n ->
- pr " args.%s.%s_val = (char **) %s;\n" n n n;
- pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
- | Bool n ->
- pr " args.%s = %s;\n" n n
- | Int n ->
- pr " args.%s = %s;\n" n n
+ if args = [] && optargs = [] then (
+ pr " serial = guestfs___send (g, GUESTFS_PROC_%s, progress_hint, 0,\n"
+ (String.uppercase shortname);
+ pr " NULL, NULL);\n"
+ ) else (
+ List.iter (
+ function
+ | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
+ pr " args.%s = (char *) %s;\n" n n
+ | OptString n ->
+ pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
+ | StringList n | DeviceList n ->
+ pr " args.%s.%s_val = (char **) %s;\n" n n n;
+ pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
+ | Bool n ->
+ pr " args.%s = %s;\n" n n
+ | Int n ->
+ pr " args.%s = %s;\n" n n
+ | Int64 n ->
+ pr " args.%s = %s;\n" n n
+ | FileIn _ | FileOut _ -> ()
+ | BufferIn n ->
+ pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
+ pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
+ trace_return_error ~indent:4 style;
+ pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
+ shortname;
+ pr " guestfs___end_busy (g);\n";
+ pr " return %s;\n" (string_of_errcode errcode);
+ pr " }\n";
+ pr " args.%s.%s_val = (char *) %s;\n" n n n;
+ pr " args.%s.%s_len = %s_size;\n" n n n
+ | Pointer _ -> assert false
+ ) args;
+
+ List.iter (
+ fun argt ->
+ let n = name_of_argt argt in
+ let uc_shortname = String.uppercase shortname in
+ let uc_n = String.uppercase n in
+ pr " if ((optargs->bitmask & GUESTFS_%s_%s_BITMASK))\n"
+ uc_shortname uc_n;
+ (match argt with
+ | Bool n
+ | Int n
| Int64 n ->
- pr " args.%s = %s;\n" n n
- | FileIn _ | FileOut _ -> ()
- | BufferIn n ->
- pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
- pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
- pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
- shortname;
- pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
- pr " }\n";
- pr " args.%s.%s_val = (char *) %s;\n" n n n;
- pr " args.%s.%s_len = %s_size;\n" n n n
- | Pointer _ -> assert false
- ) args;
- pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
- (String.uppercase shortname);
- pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
- name;
+ pr " args.%s = optargs->%s;\n" n n;
+ pr " else\n";
+ pr " args.%s = 0;\n" n
+ | String n ->
+ pr " args.%s = (char *) optargs->%s;\n" n n;
+ pr " else\n";
+ pr " args.%s = (char *) \"\";\n" n
+ | _ -> assert false
+ )
+ ) optargs;
+
+ pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
+ (String.uppercase shortname);
+ pr " progress_hint, %s,\n"
+ (if optargs <> [] then "optargs->bitmask" else "0");
+ pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
+ name;
);
pr " if (serial == -1) {\n";
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ trace_return_error ~indent:4 style;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
pr " r = guestfs___send_file (g, %s);\n" n;
pr " if (r == -1) {\n";
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ trace_return_error ~indent:4 style;
+ pr " /* daemon will send an error reply which we discard */\n";
+ pr " guestfs___recv_discard (g, \"%s\");\n" shortname;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr " if (r == -2) /* daemon cancelled */\n";
pr " goto read_reply;\n";
pr " if (r == -1) {\n";
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ trace_return_error ~indent:4 style;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
(String.uppercase shortname);
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ trace_return_error ~indent:4 style;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
+ trace_return_error ~indent:4 style;
pr " int errnum = 0;\n";
pr " if (err.errno_string[0] != '\\0')\n";
pr " errnum = guestfs___string_to_errno (err.errno_string);\n";
pr " free (err.error_message);\n";
pr " free (err.errno_string);\n";
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
| FileOut n ->
pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
pr " guestfs___end_busy (g);\n";
- pr " return %s;\n" error_code;
+ trace_return_error ~indent:4 style;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
| _ -> ()
pr " guestfs___end_busy (g);\n";
(match ret with
- | RErr -> pr " return 0;\n"
+ | RErr ->
+ pr " ret_v = 0;\n"
| RInt n | RInt64 n | RBool n ->
- pr " return ret.%s;\n" n
+ pr " ret_v = ret.%s;\n" n
| RConstString _ | RConstOptString _ ->
failwithf "RConstString|RConstOptString cannot be used by daemon functions"
| RString n ->
- pr " return ret.%s; /* caller will free */\n" n
+ pr " ret_v = ret.%s; /* caller will free */\n" n
| RStringList n | RHashtable n ->
pr " /* caller will free this, but we need to add a NULL entry */\n";
pr " ret.%s.%s_val =\n" n n;
pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
n n;
pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
- pr " return ret.%s.%s_val;\n" n n
+ pr " ret_v = ret.%s.%s_val;\n" n n
| RStruct (n, _) ->
pr " /* caller will free this */\n";
- pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
+ pr " ret_v = safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
| RStructList (n, _) ->
pr " /* caller will free this */\n";
- pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
+ pr " ret_v = safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
| RBufferOut n ->
pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
pr " * _val might be NULL here. To make the API saner for\n";
pr " */\n";
pr " if (ret.%s.%s_len > 0) {\n" n n;
pr " *size_r = ret.%s.%s_len;\n" n n;
- pr " return ret.%s.%s_val; /* caller will free */\n" n n;
+ pr " ret_v = ret.%s.%s_val; /* caller will free */\n" n n;
pr " } else {\n";
pr " free (ret.%s.%s_val);\n" n n;
pr " char *p = safe_malloc (g, 1);\n";
pr " *size_r = ret.%s.%s_len;\n" n n;
- pr " return p;\n";
+ pr " ret_v = p;\n";
pr " }\n";
);
-
+ trace_return style "ret_v";
+ pr " return ret_v;\n";
pr "}\n\n"
) daemon_functions;
| [] -> "g"
| args -> name_of_argt (List.hd (List.rev args)) in
- let rerrcode, rtype =
+ let rtype =
match ret with
- | RErr | RInt _ | RBool _ -> "-1", "int "
- | RInt64 _ -> "-1", "int64_t "
- | RConstString _ | RConstOptString _ -> "NULL", "const char *"
- | RString _ | RBufferOut _ -> "NULL", "char *"
- | RStringList _ | RHashtable _ -> "NULL", "char **"
- | RStruct (_, typ) -> "NULL", sprintf "struct guestfs_%s *" typ
+ | RErr | RInt _ | RBool _ -> "int "
+ | RInt64 _ -> "int64_t "
+ | RConstString _ | RConstOptString _ -> "const char *"
+ | RString _ | RBufferOut _ -> "char *"
+ | RStringList _ | RHashtable _ -> "char **"
+ | RStruct (_, typ) -> sprintf "struct guestfs_%s *" typ
| RStructList (_, typ) ->
- "NULL", sprintf "struct guestfs_%s_list *" typ in
+ sprintf "struct guestfs_%s_list *" typ in
(* The regular variable args function, just calls the _va variant. *)
generate_prototype ~extern:false ~semicolon:false ~newline:true
pr " break;\n";
) optargs;
+ let errcode =
+ match errcode_of_ret ret with
+ | `CannotReturnError -> assert false
+ | (`ErrorIsMinusOne | `ErrorIsNULL) as e -> e in
+
pr " default:\n";
pr " error (g, \"%%s: unknown option %%d (this can happen if a program is compiled against a newer version of libguestfs, then dynamically linked to an older version)\",\n";
pr " \"%s\", i);\n" shortname;
- pr " return %s;\n" rerrcode;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr "\n";
pr " uint64_t i_mask = UINT64_C(1) << i;\n";
pr " if (optargs_s.bitmask & i_mask) {\n";
pr " error (g, \"%%s: same optional argument specified more than once\",\n";
pr " \"%s\");\n" shortname;
- pr " return %s;\n" rerrcode;
+ pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr " optargs_s.bitmask |= i_mask;\n";
pr " }\n";
"guestfs_safe_strdup";
"guestfs_safe_memdup";
"guestfs_tmpdir";
+ "guestfs___for_each_disk";
] in
let functions =
List.flatten (