This uses the L<blockdev(8)> command.");
-(*
("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
[],
"upload a file from the local machine",
C<filename> can also be a named pipe.
See also C<guestfs_upload>, C<guestfs_cat>.");
-*)
]
(* Message header, etc. *)
pr "\
+/* The communication protocol is now documented in the guestfs(3)
+ * manpage.
+ */
+
const GUESTFS_PROGRAM = 0x2000F5F5;
const GUESTFS_PROTOCOL_VERSION = 1;
+/* These constants must be larger than any possible message length. */
+const GUESTFS_LAUNCH_FLAG = 0xf5f55f5f;
+const GUESTFS_CANCEL_FLAG = 0xffffeeee;
+
enum guestfs_message_direction {
GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
string error_message<GUESTFS_ERROR_LEN>;
};
-/* For normal requests and replies (not involving any FileIn or
- * FileOut parameters), the protocol is:
- *
- * For requests:
- * total length (header + args, but not including length word itself)
- * header
- * guestfs_foo_args struct
- * For replies:
- * total length (as above)
- * header
- * guestfs_foo_ret struct
- */
-
struct guestfs_message_header {
unsigned prog; /* GUESTFS_PROGRAM */
unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
guestfs_message_status status;
};
-/* Chunked encoding used to transfer files, for FileIn and FileOut
- * parameters.
- *
- * For requests which have >= 1 FileIn parameter:
- * length of header + args (but not length word itself, and not chunks)
- * header
- * guestfs_foo_args struct
- * sequence of chunks for FileIn param #0
- * sequence of chunks for FileIn param #1 etc
- *
- * For replies which have >= 1 FileOut parameter:
- * length of header + ret (but not length word itself, and not chunks)
- * header
- * guestfs_foo_ret struct
- * sequence of chunks for FileOut param #0
- * sequence of chunks for FileOut param #1 etc
- */
const GUESTFS_MAX_CHUNK_SIZE = 8192;
struct guestfs_chunk {
pr " /* This flag is set by the callbacks, so we know we've done\n";
pr " * the callbacks as expected, and in the right sequence.\n";
pr " * 0 = not called, 1 = send called,\n";
- pr " * 2.. = send_file called,\n";
- pr " * 1000 = reply called.\n";
+ pr " * 1001 = reply called.\n";
pr " */\n";
pr " int cb_sequence;\n";
pr " struct guestfs_message_header hdr;\n";
pr "};\n";
pr "\n";
- (* Generate the send callback function. *)
- pr "static void %s_send_cb (guestfs_h *g, void *data)\n" shortname;
- pr "{\n";
- pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
- pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
- pr "\n";
- pr " guestfs__switch_to_receiving (g);\n";
- pr " ctx->cb_sequence = 1;\n";
- pr " ml->main_loop_quit (ml, g);\n";
- pr "}\n";
- pr "\n";
-
(* Generate the reply callback function. *)
pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
pr "{\n";
pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
pr "\n";
+ pr " ml->main_loop_quit (ml, g);\n";
+ pr "\n";
pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
pr " return;\n";
);
pr " done:\n";
- pr " ctx->cb_sequence = 1000;\n";
- pr " ml->main_loop_quit (ml, g);\n";
+ pr " ctx->cb_sequence = 1001;\n";
pr "}\n\n";
(* Generate the action stub. *)
pr " memset (&ctx, 0, sizeof ctx);\n";
pr "\n";
- (* Dispatch the main header and arguments. *)
+ (* Send the main header and arguments. *)
(match snd style with
| [] ->
- pr " serial = guestfs__send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
+ pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
(String.uppercase shortname)
| args ->
List.iter (
pr " args.%s = %s;\n" n n
| FileIn _ | FileOut _ -> ()
) args;
- pr " serial = guestfs__send (g, GUESTFS_PROC_%s,\n"
+ pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
(String.uppercase shortname);
pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
name;
pr " return %s;\n" error_code;
pr "\n";
- (* Send the request. *)
- pr " ctx.cb_sequence = 0;\n";
- pr " guestfs_set_send_callback (g, %s_send_cb, &ctx);\n" shortname;
- pr " (void) ml->main_loop_run (ml, g);\n";
- pr " guestfs_set_send_callback (g, NULL, NULL);\n";
- pr " if (ctx.cb_sequence != 1) {\n";
- pr " error (g, \"%%s send failed, see earlier error messages\", \"%s\");\n" name;
- pr " return %s;\n" error_code;
- pr " }\n";
- pr "\n";
-
- (* Send any additional files requested. *)
+ (* Send any additional files (FileIn) requested. *)
List.iter (
function
| FileIn n ->
- pr " if (send_file (g, %s) == -1)\n" n;
+ pr " if (guestfs__send_file_sync (g, %s) == -1)\n" n;
pr " return %s;\n" error_code;
pr "\n";
| _ -> ()
) (snd style);
(* Wait for the reply from the remote end. *)
+ pr " guestfs__switch_to_receiving (g);\n";
pr " ctx.cb_sequence = 0;\n";
pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
pr " (void) ml->main_loop_run (ml, g);\n";
pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
- pr " if (ctx.cb_sequence != 1000) {\n";
+ pr " if (ctx.cb_sequence != 1001) {\n";
pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
pr " return %s;\n" error_code;
pr " }\n";
List.iter (
function
| FileOut n ->
- pr " if (receive_file (g, %s) == -1)\n" n;
+ pr " if (guestfs__receive_file_sync (g, %s) == -1)\n" n;
pr " return %s;\n" error_code;
pr "\n";
| _ -> ()