diff options
author | Richard Jones <rjones@redhat.com> | 2009-04-03 17:24:35 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-04-03 17:24:35 +0100 |
commit | 40ca9a57829f2e82362e391d7d998bf33c8bd671 (patch) | |
tree | 39990f925b9ae363af6d219a985a70adec9af016 /src | |
parent | cd2fd58da3f5648a62f3fb7586cdc910c09a31af (diff) | |
download | libguestfs-40ca9a57829f2e82362e391d7d998bf33c8bd671.tar.gz libguestfs-40ca9a57829f2e82362e391d7d998bf33c8bd671.tar.xz libguestfs-40ca9a57829f2e82362e391d7d998bf33c8bd671.zip |
Daemon and library are mostly talking to each other now.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 26 | ||||
-rwxr-xr-x | src/generator.ml | 133 | ||||
-rw-r--r-- | src/guestfs-actions.c | 45 | ||||
-rw-r--r-- | src/guestfs.c | 178 | ||||
-rw-r--r-- | src/guestfs_protocol.c | 78 | ||||
-rw-r--r-- | src/guestfs_protocol.h | 85 | ||||
-rw-r--r-- | src/guestfs_protocol.x | 30 |
7 files changed, 530 insertions, 45 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a0066dbf..68cabba7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,5 +17,27 @@ lib_LTLIBRARIES = libguestfs.la -libguestfs_la_SOURCES = guestfs.c guestfs.h -libguestfs_la_CFLAGS = -Wall -Werror
\ No newline at end of file +# NB. guestfs-actions.c is #include'd into guestfs.c, so it should not +# be listed as a source file. +EXTRA_DIST = guestfs-actions.c + +libguestfs_la_SOURCES = \ + guestfs.c \ + guestfs.h \ + guestfs_protocol.c \ + guestfs_protocol.h \ + guestfs-actions.h + +libguestfs_la_CFLAGS = -Wall + +if RPCGEN +guestfs_protocol.c: guestfs_protocol.x + rm -f $@-t + $(RPCGEN) -c -o $@-t $< + mv $@-t $@ + +guestfs_protocol.h: guestfs_protocol.x + rm -f $@-t + $(RPCGEN) -h -o $@-t $< + mv $@-t $@ +endif
\ No newline at end of file diff --git a/src/generator.ml b/src/generator.ml index d08e2692..8588cf31 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -41,7 +41,7 @@ and argt = | String of string (* const char *name, cannot be NULL *) let functions = [ - ("mount", (Err, P2 (String "device", String "mountpoint")), + ("mount", (Err, P2 (String "device", String "mountpoint")), 1, "Mount a guest disk at a position in the filesystem", "\ Mount a guest disk at a position in the filesystem. Block devices @@ -55,7 +55,7 @@ first be mounted on C</> before others can be mounted. Other filesystems can only be mounted on directories which already exist."); - ("sync", (Err, P0), + ("sync", (Err, P0), 2, "Sync disks, writes are flushed through to the disk image", "\ This syncs the disk, so that any writes are flushed through to the @@ -64,7 +64,7 @@ underlying disk image. You should always call this if you have modified a disk image, before calling C<guestfs_close>."); - ("touch", (Err, P1 (String "path")), + ("touch", (Err, P1 (String "path")), 3, "Update file timestamps or create a new file", "\ Touch acts like the L<touch(1)> command. It can be used to @@ -137,11 +137,11 @@ let rec generate_header comment license = (* Generate the pod documentation for the C API. *) and generate_pod () = List.iter ( - fun (shortname, style, _, longdesc) -> + fun (shortname, style, _, _, longdesc) -> let name = "guestfs_" ^ shortname in pr "=head2 %s\n\n" name; pr " "; - generate_prototype ~extern:false name style; + generate_prototype ~extern:false ~handle:"handle" name style; pr "\n\n"; pr "%s\n\n" longdesc; (match style with @@ -153,8 +153,9 @@ and generate_pod () = (* Generate the protocol (XDR) file. *) and generate_xdr () = generate_header CStyle LGPLv2; + List.iter ( - fun (shortname, style, _, _) -> + fun (shortname, style, _, _, _) -> let name = "guestfs_" ^ shortname in pr "/* %s */\n\n" name; (match style with @@ -169,30 +170,76 @@ and generate_xdr () = ); (match style with | (Err, _) -> () - (* | ... -> pr "struct %s_ret ...\n" name; *) + (* | ... -> pr "struct %s_ret ...\n" name; *) ); - ) functions + ) functions; + + (* Table of procedure numbers. *) + pr "enum guestfs_procedure {\n"; + List.iter ( + fun (shortname, _, proc_nr, _, _) -> + pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr + ) functions; + pr " GUESTFS_PROC_dummy\n"; (* so we don't have a "hanging comma" *) + pr "};\n"; + pr "\n"; + + (* Having to choose a maximum message size is annoying for several + * reasons (it limits what we can do in the API), but it (a) makes + * the protocol a lot simpler, and (b) provides a bound on the size + * of the daemon which operates in limited memory space. For large + * file transfers you should use FTP. + *) + pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024); + pr "\n"; + + (* Message header, etc. *) + pr "\ +const GUESTFS_PROGRAM = 0x2000F5F5; +const GUESTFS_PROTOCOL_VERSION = 1; + +enum guestfs_message_direction { + GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */ + GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */ +}; + +enum guestfs_message_status { + GUESTFS_STATUS_OK = 0, + GUESTFS_STATUS_ERROR = 1 +}; + +struct guestfs_message_header { + unsigned prog; /* GUESTFS_PROGRAM */ + unsigned vers; /* GUESTFS_PROTOCOL_VERSION */ + guestfs_procedure proc; /* GUESTFS_PROC_x */ + guestfs_message_direction direction; + unsigned serial; /* message serial number */ + guestfs_message_status status; +}; +" (* Generate the guestfs-actions.h file. *) and generate_actions_h () = generate_header CStyle LGPLv2; List.iter ( - fun (shortname, style, _, _) -> + fun (shortname, style, _, _, _) -> let name = "guestfs_" ^ shortname in - generate_prototype ~single_line:true ~newline:true name style + generate_prototype ~single_line:true ~newline:true ~handle:"handle" + name style ) functions (* Generate the client-side dispatch stubs. *) and generate_client_actions () = generate_header CStyle LGPLv2; List.iter ( - fun (shortname, style, _, _) -> + fun (shortname, style, _, _, _) -> let name = "guestfs_" ^ shortname in (* Generate the return value struct. *) pr "struct %s_rv {\n" shortname; - pr " int err_code; /* 0 or -1 */\n"; - pr " char err_str[256];\n"; + pr " int err_code; /* 0 OK or -1 error */\n"; + pr " int serial; /* serial number of reply */\n"; + pr " char err_str[256]; /* error from daemon */\n"; (match style with | (Err, _) -> () (* | _ -> pr " struct %s_ret ret;\n" name; *) @@ -204,7 +251,8 @@ and generate_client_actions () = pr "{\n"; pr " struct %s_rv *rv = (struct %s_rv *) data;\n" shortname shortname; pr "\n"; - pr " /* XXX */ rv.code = 0;\n"; + pr " /* XXX */ rv->err_code = 0;\n"; + pr " /* XXX rv->serial = ?; */\n"; pr " main_loop.main_loop_quit (g);\n"; pr "}\n\n"; @@ -224,6 +272,7 @@ and generate_client_actions () = ); pr " struct %s_rv rv;\n" shortname; + pr " int serial;\n"; pr "\n"; pr " if (g->state != READY) {\n"; pr " error (g, \"%s called from the wrong state, %%d != READY\",\n" @@ -233,18 +282,23 @@ and generate_client_actions () = pr " }\n"; (match style with - | (_, P0) -> () + | (_, P0) -> + pr " serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n" + (String.uppercase shortname) | (_, args) -> pr "\n"; iter_args ( function | String name -> pr " args.%s = (char *) %s;\n" name name ) args; - pr " if (dispatch (g, (xdrproc_t) xdr_%s_args, (char *) &args) == -1)\n" + pr " serial = dispatch (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"; ); + pr " if (serial == -1)\n"; + pr " return %s;\n" error_code; + pr "\n"; pr " rv.err_code = 42;\n"; pr " g->reply_cb_internal = %s_cb;\n" shortname; @@ -262,6 +316,8 @@ and generate_client_actions () = pr " }\n"; pr "\n"; + pr " /* XXX check serial number agrees */\n\n"; + (match style with | (Err, _) -> pr " return 0;\n" ); @@ -273,7 +329,7 @@ and generate_client_actions () = and generate_daemon_actions_h () = generate_header CStyle GPLv2; List.iter ( - fun (name, style, _, _) -> + fun (name, style, _, _, _) -> generate_prototype ~single_line:true ~newline:true ("do_" ^ name) style; ) functions @@ -284,12 +340,12 @@ and generate_daemon_actions () = pr "#include <rpc/types.h>\n"; pr "#include <rpc/xdr.h>\n"; pr "#include \"daemon.h\"\n"; - pr "#include \"../src/guest_protocol.h\"\n"; + pr "#include \"../src/guestfs_protocol.h\"\n"; pr "#include \"actions.h\"\n"; pr "\n"; List.iter ( - fun (name, style, _, _) -> + fun (name, style, _, _, _) -> (* Generate server-side stubs. *) pr "static void %s_stub (XDR *xdr_in)\n" name; pr "{\n"; @@ -335,19 +391,46 @@ and generate_daemon_actions () = ); pr "}\n\n"; - ) functions + ) functions; + + (* Dispatch function. *) + pr "void dispatch_incoming_message (XDR *xdr_in)\n"; + pr "{\n"; + pr " switch (proc_nr) {\n"; + + List.iter ( + fun (name, style, _, _, _) -> + pr " case GUESTFS_PROC_%s:\n" (String.uppercase name); + pr " %s_stub (xdr_in);\n" name; + pr " break;\n" + ) functions; + + pr " default:\n"; + pr " reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n"; + pr " }\n"; + pr "}\n"; (* Generate a C function prototype. *) and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true) ?(single_line = false) ?(newline = false) - ?(handle = "handle") name style = + ?handle name style = if extern then pr "extern "; if static then pr "static "; (match style with | (Err, _) -> pr "int " ); - pr "%s (guestfs_h *%s" name handle; - let next () = if single_line then pr ", " else pr ",\n\t\t" in + pr "%s (" name; + let comma = ref false in + (match handle with + | None -> () + | Some handle -> pr "guestfs_h *%s" handle; comma := true + ); + let next () = + if !comma then ( + if single_line then pr ", " else pr ",\n\t\t" + ); + comma := true + in iter_args ( function | String name -> next (); pr "const char *%s" name diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index db701efc..12ae6028 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -20,15 +20,17 @@ */ struct mount_rv { - int err_code; /* 0 or -1 */ - char err_str[256]; + int err_code; /* 0 OK or -1 error */ + int serial; /* serial number of reply */ + char err_str[256]; /* error from daemon */ }; static void mount_cb (guestfs_h *g, void *data, XDR *xdr) { struct mount_rv *rv = (struct mount_rv *) data; - /* XXX */ rv.code = 0; + /* XXX */ rv->err_code = 0; + /* XXX rv->serial = ?; */ main_loop.main_loop_quit (g); } @@ -38,6 +40,7 @@ int guestfs_mount (guestfs_h *g, { struct guestfs_mount_args args; struct mount_rv rv; + int serial; if (g->state != READY) { error (g, "guestfs_mount called from the wrong state, %d != READY", @@ -47,7 +50,9 @@ int guestfs_mount (guestfs_h *g, args.device = (char *) device; args.mountpoint = (char *) mountpoint; - if (dispatch (g, (xdrproc_t) xdr_guestfs_mount_args, (char *) &args) == -1) + serial = dispatch (g, GUESTFS_PROC_MOUNT, + (xdrproc_t) xdr_guestfs_mount_args, (char *) &args); + if (serial == -1) return -1; rv.err_code = 42; @@ -65,31 +70,40 @@ int guestfs_mount (guestfs_h *g, return -1; } + /* XXX check serial number agrees */ + return 0; } struct sync_rv { - int err_code; /* 0 or -1 */ - char err_str[256]; + int err_code; /* 0 OK or -1 error */ + int serial; /* serial number of reply */ + char err_str[256]; /* error from daemon */ }; static void sync_cb (guestfs_h *g, void *data, XDR *xdr) { struct sync_rv *rv = (struct sync_rv *) data; - /* XXX */ rv.code = 0; + /* XXX */ rv->err_code = 0; + /* XXX rv->serial = ?; */ main_loop.main_loop_quit (g); } int guestfs_sync (guestfs_h *g) { struct sync_rv rv; + int serial; if (g->state != READY) { error (g, "guestfs_sync called from the wrong state, %d != READY", g->state); return -1; } + serial = dispatch (g, GUESTFS_PROC_SYNC, NULL, NULL); + if (serial == -1) + return -1; + rv.err_code = 42; g->reply_cb_internal = sync_cb; g->reply_cb_internal_data = &rv; @@ -105,19 +119,23 @@ int guestfs_sync (guestfs_h *g) return -1; } + /* XXX check serial number agrees */ + return 0; } struct touch_rv { - int err_code; /* 0 or -1 */ - char err_str[256]; + int err_code; /* 0 OK or -1 error */ + int serial; /* serial number of reply */ + char err_str[256]; /* error from daemon */ }; static void touch_cb (guestfs_h *g, void *data, XDR *xdr) { struct touch_rv *rv = (struct touch_rv *) data; - /* XXX */ rv.code = 0; + /* XXX */ rv->err_code = 0; + /* XXX rv->serial = ?; */ main_loop.main_loop_quit (g); } @@ -126,6 +144,7 @@ int guestfs_touch (guestfs_h *g, { struct guestfs_touch_args args; struct touch_rv rv; + int serial; if (g->state != READY) { error (g, "guestfs_touch called from the wrong state, %d != READY", @@ -134,7 +153,9 @@ int guestfs_touch (guestfs_h *g, } args.path = (char *) path; - if (dispatch (g, (xdrproc_t) xdr_guestfs_touch_args, (char *) &args) == -1) + serial = dispatch (g, GUESTFS_PROC_TOUCH, + (xdrproc_t) xdr_guestfs_touch_args, (char *) &args); + if (serial == -1) return -1; rv.err_code = 42; @@ -152,6 +173,8 @@ int guestfs_touch (guestfs_h *g, return -1; } + /* XXX check serial number agrees */ + return 0; } diff --git a/src/guestfs.c b/src/guestfs.c index bbcf7a69..309cd15b 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -54,6 +54,7 @@ #endif #include "guestfs.h" +#include "guestfs_protocol.h" static void error (guestfs_h *g, const char *fs, ...); static void perrorf (guestfs_h *g, const char *fs, ...); @@ -64,7 +65,7 @@ static char *safe_strdup (guestfs_h *g, const char *str); static void default_error_cb (guestfs_h *g, void *data, const char *msg); static void stdout_event (void *data, int watch, int fd, int events); static void sock_read_event (void *data, int watch, int fd, int events); -//static void sock_write_event (void *data, int watch, int fd, int events); +static void sock_write_event (void *data, int watch, int fd, int events); static int select_add_handle (guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data); static int select_remove_handle (guestfs_h *g, int watch); @@ -138,7 +139,9 @@ struct guestfs_h char *msg_in; int msg_in_size, msg_in_allocated; char *msg_out; - int msg_out_size; + int msg_out_size, msg_out_pos; + + int msg_next_serial; }; guestfs_h * @@ -587,7 +590,8 @@ guestfs_launch (guestfs_h *g) if ((r == -1 && errno == EINPROGRESS) || r == 0) goto connected; - perrorf (g, "connect"); + if (errno != ENOENT) + perrorf (g, "connect"); tries--; } @@ -603,6 +607,7 @@ guestfs_launch (guestfs_h *g) free (g->msg_out); g->msg_out = NULL; g->msg_out_size = 0; + g->msg_out_pos = 0; g->stdout_watch = main_loop.add_handle (g, g->fd[1], @@ -615,9 +620,7 @@ guestfs_launch (guestfs_h *g) g->sock_watch = main_loop.add_handle (g, g->sock, - GUESTFS_HANDLE_READABLE | - GUESTFS_HANDLE_HANGUP | - GUESTFS_HANDLE_ERROR, + GUESTFS_HANDLE_READABLE, sock_read_event, g); if (g->sock_watch == -1) { error (g, "could not watch daemon communications socket"); @@ -793,7 +796,7 @@ sock_read_event (void *data, int watch, int fd, int events) if (g->verbose) fprintf (stderr, - "sock_event: %p g->state = %d, fd = %d, events = 0x%x\n", + "sock_read_event: %p g->state = %d, fd = %d, events = 0x%x\n", g, g->state, fd, events); if (g->sock != fd) { @@ -852,6 +855,13 @@ sock_read_event (void *data, int watch, int fd, int events) goto cleanup; } + /* If this happens, it's pretty bad and we've probably lost synchronization.*/ + if (len > GUESTFS_MESSAGE_MAX) { + error (g, "message length (%u) > maximum possible size (%d)", + len, GUESTFS_MESSAGE_MAX); + goto cleanup; + } + if (g->msg_in_size < len) return; /* Need more of this message. */ /* This should not happen, and if it does it probably means we've @@ -888,6 +898,160 @@ sock_read_event (void *data, int watch, int fd, int events) xdr_destroy (&xdr); } +/* The function is called whenever we can write something on the + * guestfsd (daemon inside the guest) communication socket. + */ +static void +sock_write_event (void *data, int watch, int fd, int events) +{ + guestfs_h *g = (guestfs_h *) data; + int n; + + if (g->verbose) + fprintf (stderr, + "sock_write_event: %p g->state = %d, fd = %d, events = 0x%x\n", + g, g->state, fd, events); + + if (g->sock != fd) { + error (g, "sock_write_event: internal error: %d != %d", g->sock, fd); + return; + } + + if (g->state != BUSY) { + error (g, "sock_write_event: state %d != BUSY", g->state); + return; + } + + if (g->verbose) + fprintf (stderr, "sock_write_event: writing %d bytes ...\n", + g->msg_out_size - g->msg_out_pos); + + n = write (g->sock, g->msg_out + g->msg_out_pos, + g->msg_out_size - g->msg_out_pos); + if (n == -1) { + if (errno != EAGAIN) + perrorf (g, "write"); + return; + } + + if (g->verbose) + fprintf (stderr, "sock_write_event: wrote %d bytes\n", n); + + g->msg_out_pos += n; + + /* More to write? */ + if (g->msg_out_pos < g->msg_out_size) + return; + + if (g->verbose) + fprintf (stderr, "sock_write_event: done writing, switching back to reading events\n", n); + + free (g->msg_out); + g->msg_out_pos = g->msg_out_size = 0; + + if (main_loop.remove_handle (g, g->sock_watch) == -1) { + error (g, "remove_handle failed in sock_write_event"); + return; + } + g->sock_watch = + main_loop.add_handle (g, g->sock, + GUESTFS_HANDLE_READABLE, + sock_read_event, g); + if (g->sock_watch == -1) { + error (g, "add_handle failed in sock_write_event"); + return; + } +} + +/* Dispatch a call to the remote daemon. This function just queues + * the call in msg_out, to be sent when we next enter the main loop. + * Returns -1 for error, or the message serial number. + */ +static int +dispatch (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args) +{ + char buffer[GUESTFS_MESSAGE_MAX]; + struct guestfs_message_header hdr; + XDR xdr; + unsigned len; + int serial = g->msg_next_serial++; + + if (g->state != READY) { + error (g, "dispatch: state %d != READY", g->state); + return -1; + } + + /* Serialize the header. */ + hdr.prog = GUESTFS_PROGRAM; + hdr.vers = GUESTFS_PROTOCOL_VERSION; + hdr.proc = proc_nr; + hdr.direction = GUESTFS_DIRECTION_CALL; + hdr.serial = serial; + hdr.status = GUESTFS_STATUS_OK; + + xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE); + if (!xdr_guestfs_message_header (&xdr, &hdr)) { + error (g, "xdr_guestfs_message_header failed"); + return -1; + } + + /* Serialize the args. If any, because some message types + * have no parameters. + */ + if (xdrp) { + if (!(*xdrp) (&xdr, args)) { + error (g, "dispatch failed to marshal args"); + return -1; + } + } + + len = xdr_getpos (&xdr); + xdr_destroy (&xdr); + + /* Allocate the outgoing message buffer. */ + g->msg_out = safe_malloc (g, len + 4); + + g->msg_out_size = len + 4; + g->msg_out_pos = 0; + g->state = BUSY; + + xdrmem_create (&xdr, g->msg_out, 4, XDR_ENCODE); + if (!xdr_uint32_t (&xdr, &len)) { + error (g, "xdr_uint32_t failed in dispatch"); + goto cleanup1; + } + + memcpy (g->msg_out + 4, buffer, len); + + /* Change the handle to sock_write_event. */ + if (main_loop.remove_handle (g, g->sock_watch) == -1) { + error (g, "remove_handle failed in dispatch"); + goto cleanup1; + } + g->sock_watch = + main_loop.add_handle (g, g->sock, + GUESTFS_HANDLE_WRITABLE, + sock_write_event, g); + if (g->sock_watch == -1) { + error (g, "add_handle failed in dispatch"); + goto cleanup1; + } + + return serial; + + cleanup1: + free (g->msg_out); + g->msg_out = NULL; + g->msg_out_size = 0; + g->state = READY; + return -1; +} + +/* The high-level actions are autogenerated by generator.ml. Include + * them here. + */ +#include "guestfs-actions.c" + /* This is the default main loop implementation, using select(2). */ struct handle_cb_data { diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c new file mode 100644 index 00000000..8a590852 --- /dev/null +++ b/src/guestfs_protocol.c @@ -0,0 +1,78 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "guestfs_protocol.h" + +bool_t +xdr_guestfs_mount_args (XDR *xdrs, guestfs_mount_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->mountpoint, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_touch_args (XDR *xdrs, guestfs_touch_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->path, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_message_direction (XDR *xdrs, guestfs_message_direction *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_message_status (XDR *xdrs, guestfs_message_status *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_message_header (XDR *xdrs, guestfs_message_header *objp) +{ + register int32_t *buf; + + if (!xdr_u_int (xdrs, &objp->prog)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->vers)) + return FALSE; + if (!xdr_guestfs_procedure (xdrs, &objp->proc)) + return FALSE; + if (!xdr_guestfs_message_direction (xdrs, &objp->direction)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->serial)) + return FALSE; + if (!xdr_guestfs_message_status (xdrs, &objp->status)) + return FALSE; + return TRUE; +} diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h new file mode 100644 index 00000000..562d72fc --- /dev/null +++ b/src/guestfs_protocol.h @@ -0,0 +1,85 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _GUESTFS_PROTOCOL_H_RPCGEN +#define _GUESTFS_PROTOCOL_H_RPCGEN + +#include <rpc/rpc.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct guestfs_mount_args { + char *device; + char *mountpoint; +}; +typedef struct guestfs_mount_args guestfs_mount_args; + +struct guestfs_touch_args { + char *path; +}; +typedef struct guestfs_touch_args guestfs_touch_args; + +enum guestfs_procedure { + GUESTFS_PROC_MOUNT = 1, + GUESTFS_PROC_SYNC = 2, + GUESTFS_PROC_TOUCH = 3, + GUESTFS_PROC_dummy = 3 + 1, +}; +typedef enum guestfs_procedure guestfs_procedure; +#define GUESTFS_MESSAGE_MAX 4194304 +#define GUESTFS_PROGRAM 0x2000F5F5 +#define GUESTFS_PROTOCOL_VERSION 1 + +enum guestfs_message_direction { + GUESTFS_DIRECTION_CALL = 0, + GUESTFS_DIRECTION_REPLY = 1, +}; +typedef enum guestfs_message_direction guestfs_message_direction; + +enum guestfs_message_status { + GUESTFS_STATUS_OK = 0, + GUESTFS_STATUS_ERROR = 1, +}; +typedef enum guestfs_message_status guestfs_message_status; + +struct guestfs_message_header { + u_int prog; + u_int vers; + guestfs_procedure proc; + guestfs_message_direction direction; + u_int serial; + guestfs_message_status status; +}; +typedef struct guestfs_message_header guestfs_message_header; + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_guestfs_mount_args (XDR *, guestfs_mount_args*); +extern bool_t xdr_guestfs_touch_args (XDR *, guestfs_touch_args*); +extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*); +extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*); +extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*); +extern bool_t xdr_guestfs_message_header (XDR *, guestfs_message_header*); + +#else /* K&R C */ +extern bool_t xdr_guestfs_mount_args (); +extern bool_t xdr_guestfs_touch_args (); +extern bool_t xdr_guestfs_procedure (); +extern bool_t xdr_guestfs_message_direction (); +extern bool_t xdr_guestfs_message_status (); +extern bool_t xdr_guestfs_message_header (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_GUESTFS_PROTOCOL_H_RPCGEN */ diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x index 6569d276..1641b3d1 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -34,3 +34,33 @@ struct guestfs_touch_args { string path<>; }; +enum guestfs_procedure { + GUESTFS_PROC_MOUNT = 1, + GUESTFS_PROC_SYNC = 2, + GUESTFS_PROC_TOUCH = 3, + GUESTFS_PROC_dummy +}; + +const GUESTFS_MESSAGE_MAX = 4194304; + +const GUESTFS_PROGRAM = 0x2000F5F5; +const GUESTFS_PROTOCOL_VERSION = 1; + +enum guestfs_message_direction { + GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */ + GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */ +}; + +enum guestfs_message_status { + GUESTFS_STATUS_OK = 0, + GUESTFS_STATUS_ERROR = 1 +}; + +struct guestfs_message_header { + unsigned prog; /* GUESTFS_PROGRAM */ + unsigned vers; /* GUESTFS_PROTOCOL_VERSION */ + guestfs_procedure proc; /* GUESTFS_PROC_x */ + guestfs_message_direction direction; + unsigned serial; /* message serial number */ + guestfs_message_status status; +}; |