+#if 0
+static int cancel = 0; /* XXX Implement file cancellation. */
+
+static int
+send_file (guestfs_h *g, const char *filename)
+{
+ char buf[GUESTFS_MAX_CHUNK_SIZE];
+ int fd, r;
+
+ fd = open (filename, O_RDONLY);
+ if (fd == -1) {
+ perrorf (g, "open: %s", filename);
+ send_file_cancellation (g);
+ /* Daemon sees cancellation and won't reply, so caller can
+ * just return here.
+ */
+ return -1;
+ }
+
+ /* Send file in chunked encoding. */
+ while (!cancel && (r = read (fd, buf, sizeof buf)) > 0) {
+ if (send_file_data (g, buf, r) == -1)
+ return -1;
+ }
+
+ if (cancel) {
+ send_file_cancellation (g);
+ return -1;
+ }
+
+ if (r == -1) {
+ perrorf (g, "read: %s", filename);
+ send_file_cancellation (g);
+ return -1;
+ }
+
+ /* End of file, but before we send that, we need to close
+ * the file and check for errors.
+ */
+ if (close (fd) == -1) {
+ perrorf (g, "close: %s", filename);
+ send_file_cancellation (g);
+ return -1;
+ }
+
+ return send_file_complete (g);
+}
+
+/* Send a chunk, cancellation or end of file, wait for it to go. */
+static int
+send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t len)
+{
+ void *data;
+ guestfs_chunk chunk;
+ XDR xdr;
+
+ if (g->state != BUSY) {
+ error (g, "send_file_chunk: state %d != READY", g->state);
+ return -1;
+ }
+
+ /* Serialize the chunk. */
+ chunk.cancel = cancel;
+ chunk.data.data_len = len;
+ chunk.data.data_val = (char *) buf;
+
+ data = safe_malloc (g, GUESTFS_MAX_CHUNK_SIZE + 48);
+ xdrmem_create (&xdr, data, GUESTFS_MAX_CHUNK_SIZE + 48, XDR_ENCODE);
+ if (xdr_guestfs_chunk (&xdr, &chunk)) {
+ error (g, "xdr_guestfs_chunk failed");
+ free (data);
+ return -1;
+ }
+
+ chunkdatalen = xdr_getpos (&xdr);
+ xdr_destroy (&xdr);
+
+ len = xdr_getpos (&xdr);
+ xdr_destroy (&xdr);
+
+ data = safe_realloc (g, data, len);
+ g->msg_out = data;
+ g->msg_out_size = len;
+ g->msg_out_pos = 0;
+
+ /* Change the handle to sock_write_event. */
+ if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
+ error (g, "remove_handle failed in dispatch");
+ goto cleanup1;
+ }
+ g->sock_watch =
+ g->main_loop->add_handle (g->main_loop, g, g->sock,
+ GUESTFS_HANDLE_WRITABLE,
+ sock_write_event, NULL);
+ if (g->sock_watch == -1) {
+ error (g, "add_handle failed in dispatch");
+ goto cleanup1;
+ }
+
+ return 0;
+
+ cleanup1:
+ free (g->msg_out);
+ g->msg_out = NULL;
+ g->msg_out_size = 0;
+ g->state = READY;
+ return -1;
+}
+
+/* Send a chunk of file data. */
+static int
+send_file_data (guestfs_h *g, const char *buf, size_t len)
+{
+ return send_file_chunk (g, 0, buf, len);
+}
+
+/* Send a cancellation message. */
+static int
+send_file_cancellation (guestfs_h *g)
+{
+ char buf[1];
+ return send_file_chunk (g, 1, buf, 0);
+}
+
+/* Send a file complete chunk. */
+static int
+send_file_complete (guestfs_h *g)
+{
+ char buf[0];
+ return send_file_chunk (g, 0, buf, 0);
+}
+#endif
+