Implement _send_sync, _send_file_sync and _receive_file_sync.
[libguestfs.git] / src / guestfs-actions.c
1 /* libguestfs generated file
2  * WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
3  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
4  *
5  * Copyright (C) 2009 Red Hat Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "guestfs.h"
26 #include "guestfs_protocol.h"
27
28 #define error guestfs_error
29 #define perrorf guestfs_perrorf
30 #define safe_malloc guestfs_safe_malloc
31 #define safe_realloc guestfs_safe_realloc
32 #define safe_strdup guestfs_safe_strdup
33 #define safe_memdup guestfs_safe_memdup
34
35 /* Check the return message from a call for validity. */
36 static int
37 check_reply_header (guestfs_h *g,
38                     const struct guestfs_message_header *hdr,
39                     int proc_nr, int serial)
40 {
41   if (hdr->prog != GUESTFS_PROGRAM) {
42     error (g, "wrong program (%d/%d)", hdr->prog, GUESTFS_PROGRAM);
43     return -1;
44   }
45   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
46     error (g, "wrong protocol version (%d/%d)",
47            hdr->vers, GUESTFS_PROTOCOL_VERSION);
48     return -1;
49   }
50   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
51     error (g, "unexpected message direction (%d/%d)",
52            hdr->direction, GUESTFS_DIRECTION_REPLY);
53     return -1;
54   }
55   if (hdr->proc != proc_nr) {
56     error (g, "unexpected procedure number (%d/%d)", hdr->proc, proc_nr);
57     return -1;
58   }
59   if (hdr->serial != serial) {
60     error (g, "unexpected serial (%d/%d)", hdr->serial, serial);
61     return -1;
62   }
63
64   return 0;
65 }
66
67 /* Check we are in the right state to run a high-level action. */
68 static int
69 check_state (guestfs_h *g, const char *caller)
70 {
71   if (!guestfs_is_ready (g)) {
72     if (guestfs_is_config (g))
73       error (g, "%s: call launch() before using this function",
74         caller);
75     else if (guestfs_is_launching (g))
76       error (g, "%s: call wait_ready() before using this function",
77         caller);
78     else
79       error (g, "%s called from the wrong state, %d != READY",
80         caller, guestfs_get_state (g));
81     return -1;
82   }
83   return 0;
84 }
85
86 struct mount_ctx {
87   /* This flag is set by the callbacks, so we know we've done
88    * the callbacks as expected, and in the right sequence.
89    * 0 = not called, 1 = send called,
90    * 1001 = reply called.
91    */
92   int cb_sequence;
93   struct guestfs_message_header hdr;
94   struct guestfs_message_error err;
95 };
96
97 static void mount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
98 {
99   guestfs_main_loop *ml = guestfs_get_main_loop (g);
100   struct mount_ctx *ctx = (struct mount_ctx *) data;
101
102   ml->main_loop_quit (ml, g);
103
104   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
105     error (g, "%s: failed to parse reply header", "guestfs_mount");
106     return;
107   }
108   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
109     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
110       error (g, "%s: failed to parse reply error", "guestfs_mount");
111       return;
112     }
113     goto done;
114   }
115  done:
116   ctx->cb_sequence = 1001;
117 }
118
119 int guestfs_mount (guestfs_h *g,
120                 const char *device,
121                 const char *mountpoint)
122 {
123   struct guestfs_mount_args args;
124   struct mount_ctx ctx;
125   guestfs_main_loop *ml = guestfs_get_main_loop (g);
126   int serial;
127
128   if (check_state (g, "guestfs_mount") == -1) return -1;
129
130   memset (&ctx, 0, sizeof ctx);
131
132   args.device = (char *) device;
133   args.mountpoint = (char *) mountpoint;
134   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT,
135         (xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
136   if (serial == -1)
137     return -1;
138
139   guestfs__switch_to_receiving (g);
140   ctx.cb_sequence = 0;
141   guestfs_set_reply_callback (g, mount_reply_cb, &ctx);
142   (void) ml->main_loop_run (ml, g);
143   guestfs_set_reply_callback (g, NULL, NULL);
144   if (ctx.cb_sequence != 1001) {
145     error (g, "%s reply failed, see earlier error messages", "guestfs_mount");
146     return -1;
147   }
148
149   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
150     return -1;
151
152   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
153     error (g, "%s", ctx.err.error_message);
154     return -1;
155   }
156
157   return 0;
158 }
159
160 struct sync_ctx {
161   /* This flag is set by the callbacks, so we know we've done
162    * the callbacks as expected, and in the right sequence.
163    * 0 = not called, 1 = send called,
164    * 1001 = reply called.
165    */
166   int cb_sequence;
167   struct guestfs_message_header hdr;
168   struct guestfs_message_error err;
169 };
170
171 static void sync_reply_cb (guestfs_h *g, void *data, XDR *xdr)
172 {
173   guestfs_main_loop *ml = guestfs_get_main_loop (g);
174   struct sync_ctx *ctx = (struct sync_ctx *) data;
175
176   ml->main_loop_quit (ml, g);
177
178   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
179     error (g, "%s: failed to parse reply header", "guestfs_sync");
180     return;
181   }
182   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
183     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
184       error (g, "%s: failed to parse reply error", "guestfs_sync");
185       return;
186     }
187     goto done;
188   }
189  done:
190   ctx->cb_sequence = 1001;
191 }
192
193 int guestfs_sync (guestfs_h *g)
194 {
195   struct sync_ctx ctx;
196   guestfs_main_loop *ml = guestfs_get_main_loop (g);
197   int serial;
198
199   if (check_state (g, "guestfs_sync") == -1) return -1;
200
201   memset (&ctx, 0, sizeof ctx);
202
203   serial = guestfs__send_sync (g, GUESTFS_PROC_SYNC, NULL, NULL);
204   if (serial == -1)
205     return -1;
206
207   guestfs__switch_to_receiving (g);
208   ctx.cb_sequence = 0;
209   guestfs_set_reply_callback (g, sync_reply_cb, &ctx);
210   (void) ml->main_loop_run (ml, g);
211   guestfs_set_reply_callback (g, NULL, NULL);
212   if (ctx.cb_sequence != 1001) {
213     error (g, "%s reply failed, see earlier error messages", "guestfs_sync");
214     return -1;
215   }
216
217   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SYNC, serial) == -1)
218     return -1;
219
220   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
221     error (g, "%s", ctx.err.error_message);
222     return -1;
223   }
224
225   return 0;
226 }
227
228 struct touch_ctx {
229   /* This flag is set by the callbacks, so we know we've done
230    * the callbacks as expected, and in the right sequence.
231    * 0 = not called, 1 = send called,
232    * 1001 = reply called.
233    */
234   int cb_sequence;
235   struct guestfs_message_header hdr;
236   struct guestfs_message_error err;
237 };
238
239 static void touch_reply_cb (guestfs_h *g, void *data, XDR *xdr)
240 {
241   guestfs_main_loop *ml = guestfs_get_main_loop (g);
242   struct touch_ctx *ctx = (struct touch_ctx *) data;
243
244   ml->main_loop_quit (ml, g);
245
246   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
247     error (g, "%s: failed to parse reply header", "guestfs_touch");
248     return;
249   }
250   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
251     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
252       error (g, "%s: failed to parse reply error", "guestfs_touch");
253       return;
254     }
255     goto done;
256   }
257  done:
258   ctx->cb_sequence = 1001;
259 }
260
261 int guestfs_touch (guestfs_h *g,
262                 const char *path)
263 {
264   struct guestfs_touch_args args;
265   struct touch_ctx ctx;
266   guestfs_main_loop *ml = guestfs_get_main_loop (g);
267   int serial;
268
269   if (check_state (g, "guestfs_touch") == -1) return -1;
270
271   memset (&ctx, 0, sizeof ctx);
272
273   args.path = (char *) path;
274   serial = guestfs__send_sync (g, GUESTFS_PROC_TOUCH,
275         (xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
276   if (serial == -1)
277     return -1;
278
279   guestfs__switch_to_receiving (g);
280   ctx.cb_sequence = 0;
281   guestfs_set_reply_callback (g, touch_reply_cb, &ctx);
282   (void) ml->main_loop_run (ml, g);
283   guestfs_set_reply_callback (g, NULL, NULL);
284   if (ctx.cb_sequence != 1001) {
285     error (g, "%s reply failed, see earlier error messages", "guestfs_touch");
286     return -1;
287   }
288
289   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
290     return -1;
291
292   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
293     error (g, "%s", ctx.err.error_message);
294     return -1;
295   }
296
297   return 0;
298 }
299
300 struct cat_ctx {
301   /* This flag is set by the callbacks, so we know we've done
302    * the callbacks as expected, and in the right sequence.
303    * 0 = not called, 1 = send called,
304    * 1001 = reply called.
305    */
306   int cb_sequence;
307   struct guestfs_message_header hdr;
308   struct guestfs_message_error err;
309   struct guestfs_cat_ret ret;
310 };
311
312 static void cat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
313 {
314   guestfs_main_loop *ml = guestfs_get_main_loop (g);
315   struct cat_ctx *ctx = (struct cat_ctx *) data;
316
317   ml->main_loop_quit (ml, g);
318
319   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
320     error (g, "%s: failed to parse reply header", "guestfs_cat");
321     return;
322   }
323   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
324     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
325       error (g, "%s: failed to parse reply error", "guestfs_cat");
326       return;
327     }
328     goto done;
329   }
330   if (!xdr_guestfs_cat_ret (xdr, &ctx->ret)) {
331     error (g, "%s: failed to parse reply", "guestfs_cat");
332     return;
333   }
334  done:
335   ctx->cb_sequence = 1001;
336 }
337
338 char *guestfs_cat (guestfs_h *g,
339                 const char *path)
340 {
341   struct guestfs_cat_args args;
342   struct cat_ctx ctx;
343   guestfs_main_loop *ml = guestfs_get_main_loop (g);
344   int serial;
345
346   if (check_state (g, "guestfs_cat") == -1) return NULL;
347
348   memset (&ctx, 0, sizeof ctx);
349
350   args.path = (char *) path;
351   serial = guestfs__send_sync (g, GUESTFS_PROC_CAT,
352         (xdrproc_t) xdr_guestfs_cat_args, (char *) &args);
353   if (serial == -1)
354     return NULL;
355
356   guestfs__switch_to_receiving (g);
357   ctx.cb_sequence = 0;
358   guestfs_set_reply_callback (g, cat_reply_cb, &ctx);
359   (void) ml->main_loop_run (ml, g);
360   guestfs_set_reply_callback (g, NULL, NULL);
361   if (ctx.cb_sequence != 1001) {
362     error (g, "%s reply failed, see earlier error messages", "guestfs_cat");
363     return NULL;
364   }
365
366   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CAT, serial) == -1)
367     return NULL;
368
369   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
370     error (g, "%s", ctx.err.error_message);
371     return NULL;
372   }
373
374   return ctx.ret.content; /* caller will free */
375 }
376
377 struct ll_ctx {
378   /* This flag is set by the callbacks, so we know we've done
379    * the callbacks as expected, and in the right sequence.
380    * 0 = not called, 1 = send called,
381    * 1001 = reply called.
382    */
383   int cb_sequence;
384   struct guestfs_message_header hdr;
385   struct guestfs_message_error err;
386   struct guestfs_ll_ret ret;
387 };
388
389 static void ll_reply_cb (guestfs_h *g, void *data, XDR *xdr)
390 {
391   guestfs_main_loop *ml = guestfs_get_main_loop (g);
392   struct ll_ctx *ctx = (struct ll_ctx *) data;
393
394   ml->main_loop_quit (ml, g);
395
396   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
397     error (g, "%s: failed to parse reply header", "guestfs_ll");
398     return;
399   }
400   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
401     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
402       error (g, "%s: failed to parse reply error", "guestfs_ll");
403       return;
404     }
405     goto done;
406   }
407   if (!xdr_guestfs_ll_ret (xdr, &ctx->ret)) {
408     error (g, "%s: failed to parse reply", "guestfs_ll");
409     return;
410   }
411  done:
412   ctx->cb_sequence = 1001;
413 }
414
415 char *guestfs_ll (guestfs_h *g,
416                 const char *directory)
417 {
418   struct guestfs_ll_args args;
419   struct ll_ctx ctx;
420   guestfs_main_loop *ml = guestfs_get_main_loop (g);
421   int serial;
422
423   if (check_state (g, "guestfs_ll") == -1) return NULL;
424
425   memset (&ctx, 0, sizeof ctx);
426
427   args.directory = (char *) directory;
428   serial = guestfs__send_sync (g, GUESTFS_PROC_LL,
429         (xdrproc_t) xdr_guestfs_ll_args, (char *) &args);
430   if (serial == -1)
431     return NULL;
432
433   guestfs__switch_to_receiving (g);
434   ctx.cb_sequence = 0;
435   guestfs_set_reply_callback (g, ll_reply_cb, &ctx);
436   (void) ml->main_loop_run (ml, g);
437   guestfs_set_reply_callback (g, NULL, NULL);
438   if (ctx.cb_sequence != 1001) {
439     error (g, "%s reply failed, see earlier error messages", "guestfs_ll");
440     return NULL;
441   }
442
443   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LL, serial) == -1)
444     return NULL;
445
446   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
447     error (g, "%s", ctx.err.error_message);
448     return NULL;
449   }
450
451   return ctx.ret.listing; /* caller will free */
452 }
453
454 struct ls_ctx {
455   /* This flag is set by the callbacks, so we know we've done
456    * the callbacks as expected, and in the right sequence.
457    * 0 = not called, 1 = send called,
458    * 1001 = reply called.
459    */
460   int cb_sequence;
461   struct guestfs_message_header hdr;
462   struct guestfs_message_error err;
463   struct guestfs_ls_ret ret;
464 };
465
466 static void ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
467 {
468   guestfs_main_loop *ml = guestfs_get_main_loop (g);
469   struct ls_ctx *ctx = (struct ls_ctx *) data;
470
471   ml->main_loop_quit (ml, g);
472
473   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
474     error (g, "%s: failed to parse reply header", "guestfs_ls");
475     return;
476   }
477   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
478     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
479       error (g, "%s: failed to parse reply error", "guestfs_ls");
480       return;
481     }
482     goto done;
483   }
484   if (!xdr_guestfs_ls_ret (xdr, &ctx->ret)) {
485     error (g, "%s: failed to parse reply", "guestfs_ls");
486     return;
487   }
488  done:
489   ctx->cb_sequence = 1001;
490 }
491
492 char **guestfs_ls (guestfs_h *g,
493                 const char *directory)
494 {
495   struct guestfs_ls_args args;
496   struct ls_ctx ctx;
497   guestfs_main_loop *ml = guestfs_get_main_loop (g);
498   int serial;
499
500   if (check_state (g, "guestfs_ls") == -1) return NULL;
501
502   memset (&ctx, 0, sizeof ctx);
503
504   args.directory = (char *) directory;
505   serial = guestfs__send_sync (g, GUESTFS_PROC_LS,
506         (xdrproc_t) xdr_guestfs_ls_args, (char *) &args);
507   if (serial == -1)
508     return NULL;
509
510   guestfs__switch_to_receiving (g);
511   ctx.cb_sequence = 0;
512   guestfs_set_reply_callback (g, ls_reply_cb, &ctx);
513   (void) ml->main_loop_run (ml, g);
514   guestfs_set_reply_callback (g, NULL, NULL);
515   if (ctx.cb_sequence != 1001) {
516     error (g, "%s reply failed, see earlier error messages", "guestfs_ls");
517     return NULL;
518   }
519
520   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LS, serial) == -1)
521     return NULL;
522
523   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
524     error (g, "%s", ctx.err.error_message);
525     return NULL;
526   }
527
528   /* caller will free this, but we need to add a NULL entry */
529   ctx.ret.listing.listing_val =
530     safe_realloc (g, ctx.ret.listing.listing_val,
531                   sizeof (char *) * (ctx.ret.listing.listing_len + 1));
532   ctx.ret.listing.listing_val[ctx.ret.listing.listing_len] = NULL;
533   return ctx.ret.listing.listing_val;
534 }
535
536 struct list_devices_ctx {
537   /* This flag is set by the callbacks, so we know we've done
538    * the callbacks as expected, and in the right sequence.
539    * 0 = not called, 1 = send called,
540    * 1001 = reply called.
541    */
542   int cb_sequence;
543   struct guestfs_message_header hdr;
544   struct guestfs_message_error err;
545   struct guestfs_list_devices_ret ret;
546 };
547
548 static void list_devices_reply_cb (guestfs_h *g, void *data, XDR *xdr)
549 {
550   guestfs_main_loop *ml = guestfs_get_main_loop (g);
551   struct list_devices_ctx *ctx = (struct list_devices_ctx *) data;
552
553   ml->main_loop_quit (ml, g);
554
555   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
556     error (g, "%s: failed to parse reply header", "guestfs_list_devices");
557     return;
558   }
559   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
560     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
561       error (g, "%s: failed to parse reply error", "guestfs_list_devices");
562       return;
563     }
564     goto done;
565   }
566   if (!xdr_guestfs_list_devices_ret (xdr, &ctx->ret)) {
567     error (g, "%s: failed to parse reply", "guestfs_list_devices");
568     return;
569   }
570  done:
571   ctx->cb_sequence = 1001;
572 }
573
574 char **guestfs_list_devices (guestfs_h *g)
575 {
576   struct list_devices_ctx ctx;
577   guestfs_main_loop *ml = guestfs_get_main_loop (g);
578   int serial;
579
580   if (check_state (g, "guestfs_list_devices") == -1) return NULL;
581
582   memset (&ctx, 0, sizeof ctx);
583
584   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
585   if (serial == -1)
586     return NULL;
587
588   guestfs__switch_to_receiving (g);
589   ctx.cb_sequence = 0;
590   guestfs_set_reply_callback (g, list_devices_reply_cb, &ctx);
591   (void) ml->main_loop_run (ml, g);
592   guestfs_set_reply_callback (g, NULL, NULL);
593   if (ctx.cb_sequence != 1001) {
594     error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices");
595     return NULL;
596   }
597
598   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1)
599     return NULL;
600
601   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
602     error (g, "%s", ctx.err.error_message);
603     return NULL;
604   }
605
606   /* caller will free this, but we need to add a NULL entry */
607   ctx.ret.devices.devices_val =
608     safe_realloc (g, ctx.ret.devices.devices_val,
609                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
610   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
611   return ctx.ret.devices.devices_val;
612 }
613
614 struct list_partitions_ctx {
615   /* This flag is set by the callbacks, so we know we've done
616    * the callbacks as expected, and in the right sequence.
617    * 0 = not called, 1 = send called,
618    * 1001 = reply called.
619    */
620   int cb_sequence;
621   struct guestfs_message_header hdr;
622   struct guestfs_message_error err;
623   struct guestfs_list_partitions_ret ret;
624 };
625
626 static void list_partitions_reply_cb (guestfs_h *g, void *data, XDR *xdr)
627 {
628   guestfs_main_loop *ml = guestfs_get_main_loop (g);
629   struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data;
630
631   ml->main_loop_quit (ml, g);
632
633   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
634     error (g, "%s: failed to parse reply header", "guestfs_list_partitions");
635     return;
636   }
637   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
638     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
639       error (g, "%s: failed to parse reply error", "guestfs_list_partitions");
640       return;
641     }
642     goto done;
643   }
644   if (!xdr_guestfs_list_partitions_ret (xdr, &ctx->ret)) {
645     error (g, "%s: failed to parse reply", "guestfs_list_partitions");
646     return;
647   }
648  done:
649   ctx->cb_sequence = 1001;
650 }
651
652 char **guestfs_list_partitions (guestfs_h *g)
653 {
654   struct list_partitions_ctx ctx;
655   guestfs_main_loop *ml = guestfs_get_main_loop (g);
656   int serial;
657
658   if (check_state (g, "guestfs_list_partitions") == -1) return NULL;
659
660   memset (&ctx, 0, sizeof ctx);
661
662   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
663   if (serial == -1)
664     return NULL;
665
666   guestfs__switch_to_receiving (g);
667   ctx.cb_sequence = 0;
668   guestfs_set_reply_callback (g, list_partitions_reply_cb, &ctx);
669   (void) ml->main_loop_run (ml, g);
670   guestfs_set_reply_callback (g, NULL, NULL);
671   if (ctx.cb_sequence != 1001) {
672     error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions");
673     return NULL;
674   }
675
676   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1)
677     return NULL;
678
679   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
680     error (g, "%s", ctx.err.error_message);
681     return NULL;
682   }
683
684   /* caller will free this, but we need to add a NULL entry */
685   ctx.ret.partitions.partitions_val =
686     safe_realloc (g, ctx.ret.partitions.partitions_val,
687                   sizeof (char *) * (ctx.ret.partitions.partitions_len + 1));
688   ctx.ret.partitions.partitions_val[ctx.ret.partitions.partitions_len] = NULL;
689   return ctx.ret.partitions.partitions_val;
690 }
691
692 struct pvs_ctx {
693   /* This flag is set by the callbacks, so we know we've done
694    * the callbacks as expected, and in the right sequence.
695    * 0 = not called, 1 = send called,
696    * 1001 = reply called.
697    */
698   int cb_sequence;
699   struct guestfs_message_header hdr;
700   struct guestfs_message_error err;
701   struct guestfs_pvs_ret ret;
702 };
703
704 static void pvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
705 {
706   guestfs_main_loop *ml = guestfs_get_main_loop (g);
707   struct pvs_ctx *ctx = (struct pvs_ctx *) data;
708
709   ml->main_loop_quit (ml, g);
710
711   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
712     error (g, "%s: failed to parse reply header", "guestfs_pvs");
713     return;
714   }
715   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
716     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
717       error (g, "%s: failed to parse reply error", "guestfs_pvs");
718       return;
719     }
720     goto done;
721   }
722   if (!xdr_guestfs_pvs_ret (xdr, &ctx->ret)) {
723     error (g, "%s: failed to parse reply", "guestfs_pvs");
724     return;
725   }
726  done:
727   ctx->cb_sequence = 1001;
728 }
729
730 char **guestfs_pvs (guestfs_h *g)
731 {
732   struct pvs_ctx ctx;
733   guestfs_main_loop *ml = guestfs_get_main_loop (g);
734   int serial;
735
736   if (check_state (g, "guestfs_pvs") == -1) return NULL;
737
738   memset (&ctx, 0, sizeof ctx);
739
740   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS, NULL, NULL);
741   if (serial == -1)
742     return NULL;
743
744   guestfs__switch_to_receiving (g);
745   ctx.cb_sequence = 0;
746   guestfs_set_reply_callback (g, pvs_reply_cb, &ctx);
747   (void) ml->main_loop_run (ml, g);
748   guestfs_set_reply_callback (g, NULL, NULL);
749   if (ctx.cb_sequence != 1001) {
750     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs");
751     return NULL;
752   }
753
754   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS, serial) == -1)
755     return NULL;
756
757   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
758     error (g, "%s", ctx.err.error_message);
759     return NULL;
760   }
761
762   /* caller will free this, but we need to add a NULL entry */
763   ctx.ret.physvols.physvols_val =
764     safe_realloc (g, ctx.ret.physvols.physvols_val,
765                   sizeof (char *) * (ctx.ret.physvols.physvols_len + 1));
766   ctx.ret.physvols.physvols_val[ctx.ret.physvols.physvols_len] = NULL;
767   return ctx.ret.physvols.physvols_val;
768 }
769
770 struct vgs_ctx {
771   /* This flag is set by the callbacks, so we know we've done
772    * the callbacks as expected, and in the right sequence.
773    * 0 = not called, 1 = send called,
774    * 1001 = reply called.
775    */
776   int cb_sequence;
777   struct guestfs_message_header hdr;
778   struct guestfs_message_error err;
779   struct guestfs_vgs_ret ret;
780 };
781
782 static void vgs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
783 {
784   guestfs_main_loop *ml = guestfs_get_main_loop (g);
785   struct vgs_ctx *ctx = (struct vgs_ctx *) data;
786
787   ml->main_loop_quit (ml, g);
788
789   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
790     error (g, "%s: failed to parse reply header", "guestfs_vgs");
791     return;
792   }
793   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
794     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
795       error (g, "%s: failed to parse reply error", "guestfs_vgs");
796       return;
797     }
798     goto done;
799   }
800   if (!xdr_guestfs_vgs_ret (xdr, &ctx->ret)) {
801     error (g, "%s: failed to parse reply", "guestfs_vgs");
802     return;
803   }
804  done:
805   ctx->cb_sequence = 1001;
806 }
807
808 char **guestfs_vgs (guestfs_h *g)
809 {
810   struct vgs_ctx ctx;
811   guestfs_main_loop *ml = guestfs_get_main_loop (g);
812   int serial;
813
814   if (check_state (g, "guestfs_vgs") == -1) return NULL;
815
816   memset (&ctx, 0, sizeof ctx);
817
818   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS, NULL, NULL);
819   if (serial == -1)
820     return NULL;
821
822   guestfs__switch_to_receiving (g);
823   ctx.cb_sequence = 0;
824   guestfs_set_reply_callback (g, vgs_reply_cb, &ctx);
825   (void) ml->main_loop_run (ml, g);
826   guestfs_set_reply_callback (g, NULL, NULL);
827   if (ctx.cb_sequence != 1001) {
828     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs");
829     return NULL;
830   }
831
832   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS, serial) == -1)
833     return NULL;
834
835   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
836     error (g, "%s", ctx.err.error_message);
837     return NULL;
838   }
839
840   /* caller will free this, but we need to add a NULL entry */
841   ctx.ret.volgroups.volgroups_val =
842     safe_realloc (g, ctx.ret.volgroups.volgroups_val,
843                   sizeof (char *) * (ctx.ret.volgroups.volgroups_len + 1));
844   ctx.ret.volgroups.volgroups_val[ctx.ret.volgroups.volgroups_len] = NULL;
845   return ctx.ret.volgroups.volgroups_val;
846 }
847
848 struct lvs_ctx {
849   /* This flag is set by the callbacks, so we know we've done
850    * the callbacks as expected, and in the right sequence.
851    * 0 = not called, 1 = send called,
852    * 1001 = reply called.
853    */
854   int cb_sequence;
855   struct guestfs_message_header hdr;
856   struct guestfs_message_error err;
857   struct guestfs_lvs_ret ret;
858 };
859
860 static void lvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
861 {
862   guestfs_main_loop *ml = guestfs_get_main_loop (g);
863   struct lvs_ctx *ctx = (struct lvs_ctx *) data;
864
865   ml->main_loop_quit (ml, g);
866
867   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
868     error (g, "%s: failed to parse reply header", "guestfs_lvs");
869     return;
870   }
871   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
872     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
873       error (g, "%s: failed to parse reply error", "guestfs_lvs");
874       return;
875     }
876     goto done;
877   }
878   if (!xdr_guestfs_lvs_ret (xdr, &ctx->ret)) {
879     error (g, "%s: failed to parse reply", "guestfs_lvs");
880     return;
881   }
882  done:
883   ctx->cb_sequence = 1001;
884 }
885
886 char **guestfs_lvs (guestfs_h *g)
887 {
888   struct lvs_ctx ctx;
889   guestfs_main_loop *ml = guestfs_get_main_loop (g);
890   int serial;
891
892   if (check_state (g, "guestfs_lvs") == -1) return NULL;
893
894   memset (&ctx, 0, sizeof ctx);
895
896   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS, NULL, NULL);
897   if (serial == -1)
898     return NULL;
899
900   guestfs__switch_to_receiving (g);
901   ctx.cb_sequence = 0;
902   guestfs_set_reply_callback (g, lvs_reply_cb, &ctx);
903   (void) ml->main_loop_run (ml, g);
904   guestfs_set_reply_callback (g, NULL, NULL);
905   if (ctx.cb_sequence != 1001) {
906     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs");
907     return NULL;
908   }
909
910   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS, serial) == -1)
911     return NULL;
912
913   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
914     error (g, "%s", ctx.err.error_message);
915     return NULL;
916   }
917
918   /* caller will free this, but we need to add a NULL entry */
919   ctx.ret.logvols.logvols_val =
920     safe_realloc (g, ctx.ret.logvols.logvols_val,
921                   sizeof (char *) * (ctx.ret.logvols.logvols_len + 1));
922   ctx.ret.logvols.logvols_val[ctx.ret.logvols.logvols_len] = NULL;
923   return ctx.ret.logvols.logvols_val;
924 }
925
926 struct pvs_full_ctx {
927   /* This flag is set by the callbacks, so we know we've done
928    * the callbacks as expected, and in the right sequence.
929    * 0 = not called, 1 = send called,
930    * 1001 = reply called.
931    */
932   int cb_sequence;
933   struct guestfs_message_header hdr;
934   struct guestfs_message_error err;
935   struct guestfs_pvs_full_ret ret;
936 };
937
938 static void pvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
939 {
940   guestfs_main_loop *ml = guestfs_get_main_loop (g);
941   struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data;
942
943   ml->main_loop_quit (ml, g);
944
945   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
946     error (g, "%s: failed to parse reply header", "guestfs_pvs_full");
947     return;
948   }
949   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
950     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
951       error (g, "%s: failed to parse reply error", "guestfs_pvs_full");
952       return;
953     }
954     goto done;
955   }
956   if (!xdr_guestfs_pvs_full_ret (xdr, &ctx->ret)) {
957     error (g, "%s: failed to parse reply", "guestfs_pvs_full");
958     return;
959   }
960  done:
961   ctx->cb_sequence = 1001;
962 }
963
964 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
965 {
966   struct pvs_full_ctx ctx;
967   guestfs_main_loop *ml = guestfs_get_main_loop (g);
968   int serial;
969
970   if (check_state (g, "guestfs_pvs_full") == -1) return NULL;
971
972   memset (&ctx, 0, sizeof ctx);
973
974   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
975   if (serial == -1)
976     return NULL;
977
978   guestfs__switch_to_receiving (g);
979   ctx.cb_sequence = 0;
980   guestfs_set_reply_callback (g, pvs_full_reply_cb, &ctx);
981   (void) ml->main_loop_run (ml, g);
982   guestfs_set_reply_callback (g, NULL, NULL);
983   if (ctx.cb_sequence != 1001) {
984     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full");
985     return NULL;
986   }
987
988   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1)
989     return NULL;
990
991   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
992     error (g, "%s", ctx.err.error_message);
993     return NULL;
994   }
995
996   /* caller will free this */
997   return safe_memdup (g, &ctx.ret.physvols, sizeof (ctx.ret.physvols));
998 }
999
1000 struct vgs_full_ctx {
1001   /* This flag is set by the callbacks, so we know we've done
1002    * the callbacks as expected, and in the right sequence.
1003    * 0 = not called, 1 = send called,
1004    * 1001 = reply called.
1005    */
1006   int cb_sequence;
1007   struct guestfs_message_header hdr;
1008   struct guestfs_message_error err;
1009   struct guestfs_vgs_full_ret ret;
1010 };
1011
1012 static void vgs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1013 {
1014   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1015   struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data;
1016
1017   ml->main_loop_quit (ml, g);
1018
1019   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1020     error (g, "%s: failed to parse reply header", "guestfs_vgs_full");
1021     return;
1022   }
1023   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1024     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1025       error (g, "%s: failed to parse reply error", "guestfs_vgs_full");
1026       return;
1027     }
1028     goto done;
1029   }
1030   if (!xdr_guestfs_vgs_full_ret (xdr, &ctx->ret)) {
1031     error (g, "%s: failed to parse reply", "guestfs_vgs_full");
1032     return;
1033   }
1034  done:
1035   ctx->cb_sequence = 1001;
1036 }
1037
1038 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
1039 {
1040   struct vgs_full_ctx ctx;
1041   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1042   int serial;
1043
1044   if (check_state (g, "guestfs_vgs_full") == -1) return NULL;
1045
1046   memset (&ctx, 0, sizeof ctx);
1047
1048   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
1049   if (serial == -1)
1050     return NULL;
1051
1052   guestfs__switch_to_receiving (g);
1053   ctx.cb_sequence = 0;
1054   guestfs_set_reply_callback (g, vgs_full_reply_cb, &ctx);
1055   (void) ml->main_loop_run (ml, g);
1056   guestfs_set_reply_callback (g, NULL, NULL);
1057   if (ctx.cb_sequence != 1001) {
1058     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full");
1059     return NULL;
1060   }
1061
1062   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1)
1063     return NULL;
1064
1065   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1066     error (g, "%s", ctx.err.error_message);
1067     return NULL;
1068   }
1069
1070   /* caller will free this */
1071   return safe_memdup (g, &ctx.ret.volgroups, sizeof (ctx.ret.volgroups));
1072 }
1073
1074 struct lvs_full_ctx {
1075   /* This flag is set by the callbacks, so we know we've done
1076    * the callbacks as expected, and in the right sequence.
1077    * 0 = not called, 1 = send called,
1078    * 1001 = reply called.
1079    */
1080   int cb_sequence;
1081   struct guestfs_message_header hdr;
1082   struct guestfs_message_error err;
1083   struct guestfs_lvs_full_ret ret;
1084 };
1085
1086 static void lvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1087 {
1088   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1089   struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data;
1090
1091   ml->main_loop_quit (ml, g);
1092
1093   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1094     error (g, "%s: failed to parse reply header", "guestfs_lvs_full");
1095     return;
1096   }
1097   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1098     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1099       error (g, "%s: failed to parse reply error", "guestfs_lvs_full");
1100       return;
1101     }
1102     goto done;
1103   }
1104   if (!xdr_guestfs_lvs_full_ret (xdr, &ctx->ret)) {
1105     error (g, "%s: failed to parse reply", "guestfs_lvs_full");
1106     return;
1107   }
1108  done:
1109   ctx->cb_sequence = 1001;
1110 }
1111
1112 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
1113 {
1114   struct lvs_full_ctx ctx;
1115   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1116   int serial;
1117
1118   if (check_state (g, "guestfs_lvs_full") == -1) return NULL;
1119
1120   memset (&ctx, 0, sizeof ctx);
1121
1122   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
1123   if (serial == -1)
1124     return NULL;
1125
1126   guestfs__switch_to_receiving (g);
1127   ctx.cb_sequence = 0;
1128   guestfs_set_reply_callback (g, lvs_full_reply_cb, &ctx);
1129   (void) ml->main_loop_run (ml, g);
1130   guestfs_set_reply_callback (g, NULL, NULL);
1131   if (ctx.cb_sequence != 1001) {
1132     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full");
1133     return NULL;
1134   }
1135
1136   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1)
1137     return NULL;
1138
1139   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1140     error (g, "%s", ctx.err.error_message);
1141     return NULL;
1142   }
1143
1144   /* caller will free this */
1145   return safe_memdup (g, &ctx.ret.logvols, sizeof (ctx.ret.logvols));
1146 }
1147
1148 struct read_lines_ctx {
1149   /* This flag is set by the callbacks, so we know we've done
1150    * the callbacks as expected, and in the right sequence.
1151    * 0 = not called, 1 = send called,
1152    * 1001 = reply called.
1153    */
1154   int cb_sequence;
1155   struct guestfs_message_header hdr;
1156   struct guestfs_message_error err;
1157   struct guestfs_read_lines_ret ret;
1158 };
1159
1160 static void read_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1161 {
1162   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1163   struct read_lines_ctx *ctx = (struct read_lines_ctx *) data;
1164
1165   ml->main_loop_quit (ml, g);
1166
1167   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1168     error (g, "%s: failed to parse reply header", "guestfs_read_lines");
1169     return;
1170   }
1171   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1172     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1173       error (g, "%s: failed to parse reply error", "guestfs_read_lines");
1174       return;
1175     }
1176     goto done;
1177   }
1178   if (!xdr_guestfs_read_lines_ret (xdr, &ctx->ret)) {
1179     error (g, "%s: failed to parse reply", "guestfs_read_lines");
1180     return;
1181   }
1182  done:
1183   ctx->cb_sequence = 1001;
1184 }
1185
1186 char **guestfs_read_lines (guestfs_h *g,
1187                 const char *path)
1188 {
1189   struct guestfs_read_lines_args args;
1190   struct read_lines_ctx ctx;
1191   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1192   int serial;
1193
1194   if (check_state (g, "guestfs_read_lines") == -1) return NULL;
1195
1196   memset (&ctx, 0, sizeof ctx);
1197
1198   args.path = (char *) path;
1199   serial = guestfs__send_sync (g, GUESTFS_PROC_READ_LINES,
1200         (xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args);
1201   if (serial == -1)
1202     return NULL;
1203
1204   guestfs__switch_to_receiving (g);
1205   ctx.cb_sequence = 0;
1206   guestfs_set_reply_callback (g, read_lines_reply_cb, &ctx);
1207   (void) ml->main_loop_run (ml, g);
1208   guestfs_set_reply_callback (g, NULL, NULL);
1209   if (ctx.cb_sequence != 1001) {
1210     error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines");
1211     return NULL;
1212   }
1213
1214   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_READ_LINES, serial) == -1)
1215     return NULL;
1216
1217   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1218     error (g, "%s", ctx.err.error_message);
1219     return NULL;
1220   }
1221
1222   /* caller will free this, but we need to add a NULL entry */
1223   ctx.ret.lines.lines_val =
1224     safe_realloc (g, ctx.ret.lines.lines_val,
1225                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
1226   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
1227   return ctx.ret.lines.lines_val;
1228 }
1229
1230 struct aug_init_ctx {
1231   /* This flag is set by the callbacks, so we know we've done
1232    * the callbacks as expected, and in the right sequence.
1233    * 0 = not called, 1 = send called,
1234    * 1001 = reply called.
1235    */
1236   int cb_sequence;
1237   struct guestfs_message_header hdr;
1238   struct guestfs_message_error err;
1239 };
1240
1241 static void aug_init_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1242 {
1243   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1244   struct aug_init_ctx *ctx = (struct aug_init_ctx *) data;
1245
1246   ml->main_loop_quit (ml, g);
1247
1248   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1249     error (g, "%s: failed to parse reply header", "guestfs_aug_init");
1250     return;
1251   }
1252   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1253     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1254       error (g, "%s: failed to parse reply error", "guestfs_aug_init");
1255       return;
1256     }
1257     goto done;
1258   }
1259  done:
1260   ctx->cb_sequence = 1001;
1261 }
1262
1263 int guestfs_aug_init (guestfs_h *g,
1264                 const char *root,
1265                 int flags)
1266 {
1267   struct guestfs_aug_init_args args;
1268   struct aug_init_ctx ctx;
1269   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1270   int serial;
1271
1272   if (check_state (g, "guestfs_aug_init") == -1) return -1;
1273
1274   memset (&ctx, 0, sizeof ctx);
1275
1276   args.root = (char *) root;
1277   args.flags = flags;
1278   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INIT,
1279         (xdrproc_t) xdr_guestfs_aug_init_args, (char *) &args);
1280   if (serial == -1)
1281     return -1;
1282
1283   guestfs__switch_to_receiving (g);
1284   ctx.cb_sequence = 0;
1285   guestfs_set_reply_callback (g, aug_init_reply_cb, &ctx);
1286   (void) ml->main_loop_run (ml, g);
1287   guestfs_set_reply_callback (g, NULL, NULL);
1288   if (ctx.cb_sequence != 1001) {
1289     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init");
1290     return -1;
1291   }
1292
1293   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1)
1294     return -1;
1295
1296   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1297     error (g, "%s", ctx.err.error_message);
1298     return -1;
1299   }
1300
1301   return 0;
1302 }
1303
1304 struct aug_close_ctx {
1305   /* This flag is set by the callbacks, so we know we've done
1306    * the callbacks as expected, and in the right sequence.
1307    * 0 = not called, 1 = send called,
1308    * 1001 = reply called.
1309    */
1310   int cb_sequence;
1311   struct guestfs_message_header hdr;
1312   struct guestfs_message_error err;
1313 };
1314
1315 static void aug_close_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1316 {
1317   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1318   struct aug_close_ctx *ctx = (struct aug_close_ctx *) data;
1319
1320   ml->main_loop_quit (ml, g);
1321
1322   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1323     error (g, "%s: failed to parse reply header", "guestfs_aug_close");
1324     return;
1325   }
1326   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1327     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1328       error (g, "%s: failed to parse reply error", "guestfs_aug_close");
1329       return;
1330     }
1331     goto done;
1332   }
1333  done:
1334   ctx->cb_sequence = 1001;
1335 }
1336
1337 int guestfs_aug_close (guestfs_h *g)
1338 {
1339   struct aug_close_ctx ctx;
1340   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1341   int serial;
1342
1343   if (check_state (g, "guestfs_aug_close") == -1) return -1;
1344
1345   memset (&ctx, 0, sizeof ctx);
1346
1347   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
1348   if (serial == -1)
1349     return -1;
1350
1351   guestfs__switch_to_receiving (g);
1352   ctx.cb_sequence = 0;
1353   guestfs_set_reply_callback (g, aug_close_reply_cb, &ctx);
1354   (void) ml->main_loop_run (ml, g);
1355   guestfs_set_reply_callback (g, NULL, NULL);
1356   if (ctx.cb_sequence != 1001) {
1357     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close");
1358     return -1;
1359   }
1360
1361   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1)
1362     return -1;
1363
1364   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1365     error (g, "%s", ctx.err.error_message);
1366     return -1;
1367   }
1368
1369   return 0;
1370 }
1371
1372 struct aug_defvar_ctx {
1373   /* This flag is set by the callbacks, so we know we've done
1374    * the callbacks as expected, and in the right sequence.
1375    * 0 = not called, 1 = send called,
1376    * 1001 = reply called.
1377    */
1378   int cb_sequence;
1379   struct guestfs_message_header hdr;
1380   struct guestfs_message_error err;
1381   struct guestfs_aug_defvar_ret ret;
1382 };
1383
1384 static void aug_defvar_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1385 {
1386   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1387   struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data;
1388
1389   ml->main_loop_quit (ml, g);
1390
1391   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1392     error (g, "%s: failed to parse reply header", "guestfs_aug_defvar");
1393     return;
1394   }
1395   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1396     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1397       error (g, "%s: failed to parse reply error", "guestfs_aug_defvar");
1398       return;
1399     }
1400     goto done;
1401   }
1402   if (!xdr_guestfs_aug_defvar_ret (xdr, &ctx->ret)) {
1403     error (g, "%s: failed to parse reply", "guestfs_aug_defvar");
1404     return;
1405   }
1406  done:
1407   ctx->cb_sequence = 1001;
1408 }
1409
1410 int guestfs_aug_defvar (guestfs_h *g,
1411                 const char *name,
1412                 const char *expr)
1413 {
1414   struct guestfs_aug_defvar_args args;
1415   struct aug_defvar_ctx ctx;
1416   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1417   int serial;
1418
1419   if (check_state (g, "guestfs_aug_defvar") == -1) return -1;
1420
1421   memset (&ctx, 0, sizeof ctx);
1422
1423   args.name = (char *) name;
1424   args.expr = expr ? (char **) &expr : NULL;
1425   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFVAR,
1426         (xdrproc_t) xdr_guestfs_aug_defvar_args, (char *) &args);
1427   if (serial == -1)
1428     return -1;
1429
1430   guestfs__switch_to_receiving (g);
1431   ctx.cb_sequence = 0;
1432   guestfs_set_reply_callback (g, aug_defvar_reply_cb, &ctx);
1433   (void) ml->main_loop_run (ml, g);
1434   guestfs_set_reply_callback (g, NULL, NULL);
1435   if (ctx.cb_sequence != 1001) {
1436     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar");
1437     return -1;
1438   }
1439
1440   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1)
1441     return -1;
1442
1443   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1444     error (g, "%s", ctx.err.error_message);
1445     return -1;
1446   }
1447
1448   return ctx.ret.nrnodes;
1449 }
1450
1451 struct aug_defnode_ctx {
1452   /* This flag is set by the callbacks, so we know we've done
1453    * the callbacks as expected, and in the right sequence.
1454    * 0 = not called, 1 = send called,
1455    * 1001 = reply called.
1456    */
1457   int cb_sequence;
1458   struct guestfs_message_header hdr;
1459   struct guestfs_message_error err;
1460   struct guestfs_aug_defnode_ret ret;
1461 };
1462
1463 static void aug_defnode_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1464 {
1465   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1466   struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data;
1467
1468   ml->main_loop_quit (ml, g);
1469
1470   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1471     error (g, "%s: failed to parse reply header", "guestfs_aug_defnode");
1472     return;
1473   }
1474   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1475     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1476       error (g, "%s: failed to parse reply error", "guestfs_aug_defnode");
1477       return;
1478     }
1479     goto done;
1480   }
1481   if (!xdr_guestfs_aug_defnode_ret (xdr, &ctx->ret)) {
1482     error (g, "%s: failed to parse reply", "guestfs_aug_defnode");
1483     return;
1484   }
1485  done:
1486   ctx->cb_sequence = 1001;
1487 }
1488
1489 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
1490                 const char *name,
1491                 const char *expr,
1492                 const char *val)
1493 {
1494   struct guestfs_aug_defnode_args args;
1495   struct aug_defnode_ctx ctx;
1496   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1497   int serial;
1498
1499   if (check_state (g, "guestfs_aug_defnode") == -1) return NULL;
1500
1501   memset (&ctx, 0, sizeof ctx);
1502
1503   args.name = (char *) name;
1504   args.expr = (char *) expr;
1505   args.val = (char *) val;
1506   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFNODE,
1507         (xdrproc_t) xdr_guestfs_aug_defnode_args, (char *) &args);
1508   if (serial == -1)
1509     return NULL;
1510
1511   guestfs__switch_to_receiving (g);
1512   ctx.cb_sequence = 0;
1513   guestfs_set_reply_callback (g, aug_defnode_reply_cb, &ctx);
1514   (void) ml->main_loop_run (ml, g);
1515   guestfs_set_reply_callback (g, NULL, NULL);
1516   if (ctx.cb_sequence != 1001) {
1517     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode");
1518     return NULL;
1519   }
1520
1521   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1)
1522     return NULL;
1523
1524   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1525     error (g, "%s", ctx.err.error_message);
1526     return NULL;
1527   }
1528
1529   /* caller with free this */
1530   return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));
1531 }
1532
1533 struct aug_get_ctx {
1534   /* This flag is set by the callbacks, so we know we've done
1535    * the callbacks as expected, and in the right sequence.
1536    * 0 = not called, 1 = send called,
1537    * 1001 = reply called.
1538    */
1539   int cb_sequence;
1540   struct guestfs_message_header hdr;
1541   struct guestfs_message_error err;
1542   struct guestfs_aug_get_ret ret;
1543 };
1544
1545 static void aug_get_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1546 {
1547   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1548   struct aug_get_ctx *ctx = (struct aug_get_ctx *) data;
1549
1550   ml->main_loop_quit (ml, g);
1551
1552   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1553     error (g, "%s: failed to parse reply header", "guestfs_aug_get");
1554     return;
1555   }
1556   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1557     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1558       error (g, "%s: failed to parse reply error", "guestfs_aug_get");
1559       return;
1560     }
1561     goto done;
1562   }
1563   if (!xdr_guestfs_aug_get_ret (xdr, &ctx->ret)) {
1564     error (g, "%s: failed to parse reply", "guestfs_aug_get");
1565     return;
1566   }
1567  done:
1568   ctx->cb_sequence = 1001;
1569 }
1570
1571 char *guestfs_aug_get (guestfs_h *g,
1572                 const char *path)
1573 {
1574   struct guestfs_aug_get_args args;
1575   struct aug_get_ctx ctx;
1576   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1577   int serial;
1578
1579   if (check_state (g, "guestfs_aug_get") == -1) return NULL;
1580
1581   memset (&ctx, 0, sizeof ctx);
1582
1583   args.path = (char *) path;
1584   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_GET,
1585         (xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args);
1586   if (serial == -1)
1587     return NULL;
1588
1589   guestfs__switch_to_receiving (g);
1590   ctx.cb_sequence = 0;
1591   guestfs_set_reply_callback (g, aug_get_reply_cb, &ctx);
1592   (void) ml->main_loop_run (ml, g);
1593   guestfs_set_reply_callback (g, NULL, NULL);
1594   if (ctx.cb_sequence != 1001) {
1595     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get");
1596     return NULL;
1597   }
1598
1599   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_GET, serial) == -1)
1600     return NULL;
1601
1602   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1603     error (g, "%s", ctx.err.error_message);
1604     return NULL;
1605   }
1606
1607   return ctx.ret.val; /* caller will free */
1608 }
1609
1610 struct aug_set_ctx {
1611   /* This flag is set by the callbacks, so we know we've done
1612    * the callbacks as expected, and in the right sequence.
1613    * 0 = not called, 1 = send called,
1614    * 1001 = reply called.
1615    */
1616   int cb_sequence;
1617   struct guestfs_message_header hdr;
1618   struct guestfs_message_error err;
1619 };
1620
1621 static void aug_set_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1622 {
1623   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1624   struct aug_set_ctx *ctx = (struct aug_set_ctx *) data;
1625
1626   ml->main_loop_quit (ml, g);
1627
1628   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1629     error (g, "%s: failed to parse reply header", "guestfs_aug_set");
1630     return;
1631   }
1632   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1633     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1634       error (g, "%s: failed to parse reply error", "guestfs_aug_set");
1635       return;
1636     }
1637     goto done;
1638   }
1639  done:
1640   ctx->cb_sequence = 1001;
1641 }
1642
1643 int guestfs_aug_set (guestfs_h *g,
1644                 const char *path,
1645                 const char *val)
1646 {
1647   struct guestfs_aug_set_args args;
1648   struct aug_set_ctx ctx;
1649   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1650   int serial;
1651
1652   if (check_state (g, "guestfs_aug_set") == -1) return -1;
1653
1654   memset (&ctx, 0, sizeof ctx);
1655
1656   args.path = (char *) path;
1657   args.val = (char *) val;
1658   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SET,
1659         (xdrproc_t) xdr_guestfs_aug_set_args, (char *) &args);
1660   if (serial == -1)
1661     return -1;
1662
1663   guestfs__switch_to_receiving (g);
1664   ctx.cb_sequence = 0;
1665   guestfs_set_reply_callback (g, aug_set_reply_cb, &ctx);
1666   (void) ml->main_loop_run (ml, g);
1667   guestfs_set_reply_callback (g, NULL, NULL);
1668   if (ctx.cb_sequence != 1001) {
1669     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set");
1670     return -1;
1671   }
1672
1673   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SET, serial) == -1)
1674     return -1;
1675
1676   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1677     error (g, "%s", ctx.err.error_message);
1678     return -1;
1679   }
1680
1681   return 0;
1682 }
1683
1684 struct aug_insert_ctx {
1685   /* This flag is set by the callbacks, so we know we've done
1686    * the callbacks as expected, and in the right sequence.
1687    * 0 = not called, 1 = send called,
1688    * 1001 = reply called.
1689    */
1690   int cb_sequence;
1691   struct guestfs_message_header hdr;
1692   struct guestfs_message_error err;
1693 };
1694
1695 static void aug_insert_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1696 {
1697   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1698   struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data;
1699
1700   ml->main_loop_quit (ml, g);
1701
1702   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1703     error (g, "%s: failed to parse reply header", "guestfs_aug_insert");
1704     return;
1705   }
1706   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1707     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1708       error (g, "%s: failed to parse reply error", "guestfs_aug_insert");
1709       return;
1710     }
1711     goto done;
1712   }
1713  done:
1714   ctx->cb_sequence = 1001;
1715 }
1716
1717 int guestfs_aug_insert (guestfs_h *g,
1718                 const char *path,
1719                 const char *label,
1720                 int before)
1721 {
1722   struct guestfs_aug_insert_args args;
1723   struct aug_insert_ctx ctx;
1724   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1725   int serial;
1726
1727   if (check_state (g, "guestfs_aug_insert") == -1) return -1;
1728
1729   memset (&ctx, 0, sizeof ctx);
1730
1731   args.path = (char *) path;
1732   args.label = (char *) label;
1733   args.before = before;
1734   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INSERT,
1735         (xdrproc_t) xdr_guestfs_aug_insert_args, (char *) &args);
1736   if (serial == -1)
1737     return -1;
1738
1739   guestfs__switch_to_receiving (g);
1740   ctx.cb_sequence = 0;
1741   guestfs_set_reply_callback (g, aug_insert_reply_cb, &ctx);
1742   (void) ml->main_loop_run (ml, g);
1743   guestfs_set_reply_callback (g, NULL, NULL);
1744   if (ctx.cb_sequence != 1001) {
1745     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert");
1746     return -1;
1747   }
1748
1749   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1)
1750     return -1;
1751
1752   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1753     error (g, "%s", ctx.err.error_message);
1754     return -1;
1755   }
1756
1757   return 0;
1758 }
1759
1760 struct aug_rm_ctx {
1761   /* This flag is set by the callbacks, so we know we've done
1762    * the callbacks as expected, and in the right sequence.
1763    * 0 = not called, 1 = send called,
1764    * 1001 = reply called.
1765    */
1766   int cb_sequence;
1767   struct guestfs_message_header hdr;
1768   struct guestfs_message_error err;
1769   struct guestfs_aug_rm_ret ret;
1770 };
1771
1772 static void aug_rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1773 {
1774   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1775   struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data;
1776
1777   ml->main_loop_quit (ml, g);
1778
1779   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1780     error (g, "%s: failed to parse reply header", "guestfs_aug_rm");
1781     return;
1782   }
1783   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1784     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1785       error (g, "%s: failed to parse reply error", "guestfs_aug_rm");
1786       return;
1787     }
1788     goto done;
1789   }
1790   if (!xdr_guestfs_aug_rm_ret (xdr, &ctx->ret)) {
1791     error (g, "%s: failed to parse reply", "guestfs_aug_rm");
1792     return;
1793   }
1794  done:
1795   ctx->cb_sequence = 1001;
1796 }
1797
1798 int guestfs_aug_rm (guestfs_h *g,
1799                 const char *path)
1800 {
1801   struct guestfs_aug_rm_args args;
1802   struct aug_rm_ctx ctx;
1803   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1804   int serial;
1805
1806   if (check_state (g, "guestfs_aug_rm") == -1) return -1;
1807
1808   memset (&ctx, 0, sizeof ctx);
1809
1810   args.path = (char *) path;
1811   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_RM,
1812         (xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args);
1813   if (serial == -1)
1814     return -1;
1815
1816   guestfs__switch_to_receiving (g);
1817   ctx.cb_sequence = 0;
1818   guestfs_set_reply_callback (g, aug_rm_reply_cb, &ctx);
1819   (void) ml->main_loop_run (ml, g);
1820   guestfs_set_reply_callback (g, NULL, NULL);
1821   if (ctx.cb_sequence != 1001) {
1822     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm");
1823     return -1;
1824   }
1825
1826   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_RM, serial) == -1)
1827     return -1;
1828
1829   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1830     error (g, "%s", ctx.err.error_message);
1831     return -1;
1832   }
1833
1834   return ctx.ret.nrnodes;
1835 }
1836
1837 struct aug_mv_ctx {
1838   /* This flag is set by the callbacks, so we know we've done
1839    * the callbacks as expected, and in the right sequence.
1840    * 0 = not called, 1 = send called,
1841    * 1001 = reply called.
1842    */
1843   int cb_sequence;
1844   struct guestfs_message_header hdr;
1845   struct guestfs_message_error err;
1846 };
1847
1848 static void aug_mv_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1849 {
1850   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1851   struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data;
1852
1853   ml->main_loop_quit (ml, g);
1854
1855   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1856     error (g, "%s: failed to parse reply header", "guestfs_aug_mv");
1857     return;
1858   }
1859   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1860     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1861       error (g, "%s: failed to parse reply error", "guestfs_aug_mv");
1862       return;
1863     }
1864     goto done;
1865   }
1866  done:
1867   ctx->cb_sequence = 1001;
1868 }
1869
1870 int guestfs_aug_mv (guestfs_h *g,
1871                 const char *src,
1872                 const char *dest)
1873 {
1874   struct guestfs_aug_mv_args args;
1875   struct aug_mv_ctx ctx;
1876   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1877   int serial;
1878
1879   if (check_state (g, "guestfs_aug_mv") == -1) return -1;
1880
1881   memset (&ctx, 0, sizeof ctx);
1882
1883   args.src = (char *) src;
1884   args.dest = (char *) dest;
1885   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MV,
1886         (xdrproc_t) xdr_guestfs_aug_mv_args, (char *) &args);
1887   if (serial == -1)
1888     return -1;
1889
1890   guestfs__switch_to_receiving (g);
1891   ctx.cb_sequence = 0;
1892   guestfs_set_reply_callback (g, aug_mv_reply_cb, &ctx);
1893   (void) ml->main_loop_run (ml, g);
1894   guestfs_set_reply_callback (g, NULL, NULL);
1895   if (ctx.cb_sequence != 1001) {
1896     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv");
1897     return -1;
1898   }
1899
1900   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MV, serial) == -1)
1901     return -1;
1902
1903   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1904     error (g, "%s", ctx.err.error_message);
1905     return -1;
1906   }
1907
1908   return 0;
1909 }
1910
1911 struct aug_match_ctx {
1912   /* This flag is set by the callbacks, so we know we've done
1913    * the callbacks as expected, and in the right sequence.
1914    * 0 = not called, 1 = send called,
1915    * 1001 = reply called.
1916    */
1917   int cb_sequence;
1918   struct guestfs_message_header hdr;
1919   struct guestfs_message_error err;
1920   struct guestfs_aug_match_ret ret;
1921 };
1922
1923 static void aug_match_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1924 {
1925   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1926   struct aug_match_ctx *ctx = (struct aug_match_ctx *) data;
1927
1928   ml->main_loop_quit (ml, g);
1929
1930   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1931     error (g, "%s: failed to parse reply header", "guestfs_aug_match");
1932     return;
1933   }
1934   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1935     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1936       error (g, "%s: failed to parse reply error", "guestfs_aug_match");
1937       return;
1938     }
1939     goto done;
1940   }
1941   if (!xdr_guestfs_aug_match_ret (xdr, &ctx->ret)) {
1942     error (g, "%s: failed to parse reply", "guestfs_aug_match");
1943     return;
1944   }
1945  done:
1946   ctx->cb_sequence = 1001;
1947 }
1948
1949 char **guestfs_aug_match (guestfs_h *g,
1950                 const char *path)
1951 {
1952   struct guestfs_aug_match_args args;
1953   struct aug_match_ctx ctx;
1954   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1955   int serial;
1956
1957   if (check_state (g, "guestfs_aug_match") == -1) return NULL;
1958
1959   memset (&ctx, 0, sizeof ctx);
1960
1961   args.path = (char *) path;
1962   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MATCH,
1963         (xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args);
1964   if (serial == -1)
1965     return NULL;
1966
1967   guestfs__switch_to_receiving (g);
1968   ctx.cb_sequence = 0;
1969   guestfs_set_reply_callback (g, aug_match_reply_cb, &ctx);
1970   (void) ml->main_loop_run (ml, g);
1971   guestfs_set_reply_callback (g, NULL, NULL);
1972   if (ctx.cb_sequence != 1001) {
1973     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match");
1974     return NULL;
1975   }
1976
1977   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1)
1978     return NULL;
1979
1980   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1981     error (g, "%s", ctx.err.error_message);
1982     return NULL;
1983   }
1984
1985   /* caller will free this, but we need to add a NULL entry */
1986   ctx.ret.matches.matches_val =
1987     safe_realloc (g, ctx.ret.matches.matches_val,
1988                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
1989   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
1990   return ctx.ret.matches.matches_val;
1991 }
1992
1993 struct aug_save_ctx {
1994   /* This flag is set by the callbacks, so we know we've done
1995    * the callbacks as expected, and in the right sequence.
1996    * 0 = not called, 1 = send called,
1997    * 1001 = reply called.
1998    */
1999   int cb_sequence;
2000   struct guestfs_message_header hdr;
2001   struct guestfs_message_error err;
2002 };
2003
2004 static void aug_save_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2005 {
2006   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2007   struct aug_save_ctx *ctx = (struct aug_save_ctx *) data;
2008
2009   ml->main_loop_quit (ml, g);
2010
2011   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2012     error (g, "%s: failed to parse reply header", "guestfs_aug_save");
2013     return;
2014   }
2015   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2016     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2017       error (g, "%s: failed to parse reply error", "guestfs_aug_save");
2018       return;
2019     }
2020     goto done;
2021   }
2022  done:
2023   ctx->cb_sequence = 1001;
2024 }
2025
2026 int guestfs_aug_save (guestfs_h *g)
2027 {
2028   struct aug_save_ctx ctx;
2029   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2030   int serial;
2031
2032   if (check_state (g, "guestfs_aug_save") == -1) return -1;
2033
2034   memset (&ctx, 0, sizeof ctx);
2035
2036   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
2037   if (serial == -1)
2038     return -1;
2039
2040   guestfs__switch_to_receiving (g);
2041   ctx.cb_sequence = 0;
2042   guestfs_set_reply_callback (g, aug_save_reply_cb, &ctx);
2043   (void) ml->main_loop_run (ml, g);
2044   guestfs_set_reply_callback (g, NULL, NULL);
2045   if (ctx.cb_sequence != 1001) {
2046     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save");
2047     return -1;
2048   }
2049
2050   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1)
2051     return -1;
2052
2053   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2054     error (g, "%s", ctx.err.error_message);
2055     return -1;
2056   }
2057
2058   return 0;
2059 }
2060
2061 struct aug_load_ctx {
2062   /* This flag is set by the callbacks, so we know we've done
2063    * the callbacks as expected, and in the right sequence.
2064    * 0 = not called, 1 = send called,
2065    * 1001 = reply called.
2066    */
2067   int cb_sequence;
2068   struct guestfs_message_header hdr;
2069   struct guestfs_message_error err;
2070 };
2071
2072 static void aug_load_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2073 {
2074   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2075   struct aug_load_ctx *ctx = (struct aug_load_ctx *) data;
2076
2077   ml->main_loop_quit (ml, g);
2078
2079   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2080     error (g, "%s: failed to parse reply header", "guestfs_aug_load");
2081     return;
2082   }
2083   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2084     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2085       error (g, "%s: failed to parse reply error", "guestfs_aug_load");
2086       return;
2087     }
2088     goto done;
2089   }
2090  done:
2091   ctx->cb_sequence = 1001;
2092 }
2093
2094 int guestfs_aug_load (guestfs_h *g)
2095 {
2096   struct aug_load_ctx ctx;
2097   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2098   int serial;
2099
2100   if (check_state (g, "guestfs_aug_load") == -1) return -1;
2101
2102   memset (&ctx, 0, sizeof ctx);
2103
2104   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
2105   if (serial == -1)
2106     return -1;
2107
2108   guestfs__switch_to_receiving (g);
2109   ctx.cb_sequence = 0;
2110   guestfs_set_reply_callback (g, aug_load_reply_cb, &ctx);
2111   (void) ml->main_loop_run (ml, g);
2112   guestfs_set_reply_callback (g, NULL, NULL);
2113   if (ctx.cb_sequence != 1001) {
2114     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load");
2115     return -1;
2116   }
2117
2118   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1)
2119     return -1;
2120
2121   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2122     error (g, "%s", ctx.err.error_message);
2123     return -1;
2124   }
2125
2126   return 0;
2127 }
2128
2129 struct aug_ls_ctx {
2130   /* This flag is set by the callbacks, so we know we've done
2131    * the callbacks as expected, and in the right sequence.
2132    * 0 = not called, 1 = send called,
2133    * 1001 = reply called.
2134    */
2135   int cb_sequence;
2136   struct guestfs_message_header hdr;
2137   struct guestfs_message_error err;
2138   struct guestfs_aug_ls_ret ret;
2139 };
2140
2141 static void aug_ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2142 {
2143   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2144   struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data;
2145
2146   ml->main_loop_quit (ml, g);
2147
2148   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2149     error (g, "%s: failed to parse reply header", "guestfs_aug_ls");
2150     return;
2151   }
2152   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2153     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2154       error (g, "%s: failed to parse reply error", "guestfs_aug_ls");
2155       return;
2156     }
2157     goto done;
2158   }
2159   if (!xdr_guestfs_aug_ls_ret (xdr, &ctx->ret)) {
2160     error (g, "%s: failed to parse reply", "guestfs_aug_ls");
2161     return;
2162   }
2163  done:
2164   ctx->cb_sequence = 1001;
2165 }
2166
2167 char **guestfs_aug_ls (guestfs_h *g,
2168                 const char *path)
2169 {
2170   struct guestfs_aug_ls_args args;
2171   struct aug_ls_ctx ctx;
2172   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2173   int serial;
2174
2175   if (check_state (g, "guestfs_aug_ls") == -1) return NULL;
2176
2177   memset (&ctx, 0, sizeof ctx);
2178
2179   args.path = (char *) path;
2180   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LS,
2181         (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
2182   if (serial == -1)
2183     return NULL;
2184
2185   guestfs__switch_to_receiving (g);
2186   ctx.cb_sequence = 0;
2187   guestfs_set_reply_callback (g, aug_ls_reply_cb, &ctx);
2188   (void) ml->main_loop_run (ml, g);
2189   guestfs_set_reply_callback (g, NULL, NULL);
2190   if (ctx.cb_sequence != 1001) {
2191     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls");
2192     return NULL;
2193   }
2194
2195   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LS, serial) == -1)
2196     return NULL;
2197
2198   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2199     error (g, "%s", ctx.err.error_message);
2200     return NULL;
2201   }
2202
2203   /* caller will free this, but we need to add a NULL entry */
2204   ctx.ret.matches.matches_val =
2205     safe_realloc (g, ctx.ret.matches.matches_val,
2206                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2207   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2208   return ctx.ret.matches.matches_val;
2209 }
2210
2211 struct rm_ctx {
2212   /* This flag is set by the callbacks, so we know we've done
2213    * the callbacks as expected, and in the right sequence.
2214    * 0 = not called, 1 = send called,
2215    * 1001 = reply called.
2216    */
2217   int cb_sequence;
2218   struct guestfs_message_header hdr;
2219   struct guestfs_message_error err;
2220 };
2221
2222 static void rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2223 {
2224   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2225   struct rm_ctx *ctx = (struct rm_ctx *) data;
2226
2227   ml->main_loop_quit (ml, g);
2228
2229   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2230     error (g, "%s: failed to parse reply header", "guestfs_rm");
2231     return;
2232   }
2233   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2234     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2235       error (g, "%s: failed to parse reply error", "guestfs_rm");
2236       return;
2237     }
2238     goto done;
2239   }
2240  done:
2241   ctx->cb_sequence = 1001;
2242 }
2243
2244 int guestfs_rm (guestfs_h *g,
2245                 const char *path)
2246 {
2247   struct guestfs_rm_args args;
2248   struct rm_ctx ctx;
2249   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2250   int serial;
2251
2252   if (check_state (g, "guestfs_rm") == -1) return -1;
2253
2254   memset (&ctx, 0, sizeof ctx);
2255
2256   args.path = (char *) path;
2257   serial = guestfs__send_sync (g, GUESTFS_PROC_RM,
2258         (xdrproc_t) xdr_guestfs_rm_args, (char *) &args);
2259   if (serial == -1)
2260     return -1;
2261
2262   guestfs__switch_to_receiving (g);
2263   ctx.cb_sequence = 0;
2264   guestfs_set_reply_callback (g, rm_reply_cb, &ctx);
2265   (void) ml->main_loop_run (ml, g);
2266   guestfs_set_reply_callback (g, NULL, NULL);
2267   if (ctx.cb_sequence != 1001) {
2268     error (g, "%s reply failed, see earlier error messages", "guestfs_rm");
2269     return -1;
2270   }
2271
2272   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM, serial) == -1)
2273     return -1;
2274
2275   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2276     error (g, "%s", ctx.err.error_message);
2277     return -1;
2278   }
2279
2280   return 0;
2281 }
2282
2283 struct rmdir_ctx {
2284   /* This flag is set by the callbacks, so we know we've done
2285    * the callbacks as expected, and in the right sequence.
2286    * 0 = not called, 1 = send called,
2287    * 1001 = reply called.
2288    */
2289   int cb_sequence;
2290   struct guestfs_message_header hdr;
2291   struct guestfs_message_error err;
2292 };
2293
2294 static void rmdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2295 {
2296   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2297   struct rmdir_ctx *ctx = (struct rmdir_ctx *) data;
2298
2299   ml->main_loop_quit (ml, g);
2300
2301   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2302     error (g, "%s: failed to parse reply header", "guestfs_rmdir");
2303     return;
2304   }
2305   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2306     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2307       error (g, "%s: failed to parse reply error", "guestfs_rmdir");
2308       return;
2309     }
2310     goto done;
2311   }
2312  done:
2313   ctx->cb_sequence = 1001;
2314 }
2315
2316 int guestfs_rmdir (guestfs_h *g,
2317                 const char *path)
2318 {
2319   struct guestfs_rmdir_args args;
2320   struct rmdir_ctx ctx;
2321   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2322   int serial;
2323
2324   if (check_state (g, "guestfs_rmdir") == -1) return -1;
2325
2326   memset (&ctx, 0, sizeof ctx);
2327
2328   args.path = (char *) path;
2329   serial = guestfs__send_sync (g, GUESTFS_PROC_RMDIR,
2330         (xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args);
2331   if (serial == -1)
2332     return -1;
2333
2334   guestfs__switch_to_receiving (g);
2335   ctx.cb_sequence = 0;
2336   guestfs_set_reply_callback (g, rmdir_reply_cb, &ctx);
2337   (void) ml->main_loop_run (ml, g);
2338   guestfs_set_reply_callback (g, NULL, NULL);
2339   if (ctx.cb_sequence != 1001) {
2340     error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir");
2341     return -1;
2342   }
2343
2344   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RMDIR, serial) == -1)
2345     return -1;
2346
2347   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2348     error (g, "%s", ctx.err.error_message);
2349     return -1;
2350   }
2351
2352   return 0;
2353 }
2354
2355 struct rm_rf_ctx {
2356   /* This flag is set by the callbacks, so we know we've done
2357    * the callbacks as expected, and in the right sequence.
2358    * 0 = not called, 1 = send called,
2359    * 1001 = reply called.
2360    */
2361   int cb_sequence;
2362   struct guestfs_message_header hdr;
2363   struct guestfs_message_error err;
2364 };
2365
2366 static void rm_rf_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2367 {
2368   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2369   struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data;
2370
2371   ml->main_loop_quit (ml, g);
2372
2373   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2374     error (g, "%s: failed to parse reply header", "guestfs_rm_rf");
2375     return;
2376   }
2377   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2378     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2379       error (g, "%s: failed to parse reply error", "guestfs_rm_rf");
2380       return;
2381     }
2382     goto done;
2383   }
2384  done:
2385   ctx->cb_sequence = 1001;
2386 }
2387
2388 int guestfs_rm_rf (guestfs_h *g,
2389                 const char *path)
2390 {
2391   struct guestfs_rm_rf_args args;
2392   struct rm_rf_ctx ctx;
2393   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2394   int serial;
2395
2396   if (check_state (g, "guestfs_rm_rf") == -1) return -1;
2397
2398   memset (&ctx, 0, sizeof ctx);
2399
2400   args.path = (char *) path;
2401   serial = guestfs__send_sync (g, GUESTFS_PROC_RM_RF,
2402         (xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args);
2403   if (serial == -1)
2404     return -1;
2405
2406   guestfs__switch_to_receiving (g);
2407   ctx.cb_sequence = 0;
2408   guestfs_set_reply_callback (g, rm_rf_reply_cb, &ctx);
2409   (void) ml->main_loop_run (ml, g);
2410   guestfs_set_reply_callback (g, NULL, NULL);
2411   if (ctx.cb_sequence != 1001) {
2412     error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf");
2413     return -1;
2414   }
2415
2416   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM_RF, serial) == -1)
2417     return -1;
2418
2419   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2420     error (g, "%s", ctx.err.error_message);
2421     return -1;
2422   }
2423
2424   return 0;
2425 }
2426
2427 struct mkdir_ctx {
2428   /* This flag is set by the callbacks, so we know we've done
2429    * the callbacks as expected, and in the right sequence.
2430    * 0 = not called, 1 = send called,
2431    * 1001 = reply called.
2432    */
2433   int cb_sequence;
2434   struct guestfs_message_header hdr;
2435   struct guestfs_message_error err;
2436 };
2437
2438 static void mkdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2439 {
2440   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2441   struct mkdir_ctx *ctx = (struct mkdir_ctx *) data;
2442
2443   ml->main_loop_quit (ml, g);
2444
2445   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2446     error (g, "%s: failed to parse reply header", "guestfs_mkdir");
2447     return;
2448   }
2449   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2450     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2451       error (g, "%s: failed to parse reply error", "guestfs_mkdir");
2452       return;
2453     }
2454     goto done;
2455   }
2456  done:
2457   ctx->cb_sequence = 1001;
2458 }
2459
2460 int guestfs_mkdir (guestfs_h *g,
2461                 const char *path)
2462 {
2463   struct guestfs_mkdir_args args;
2464   struct mkdir_ctx ctx;
2465   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2466   int serial;
2467
2468   if (check_state (g, "guestfs_mkdir") == -1) return -1;
2469
2470   memset (&ctx, 0, sizeof ctx);
2471
2472   args.path = (char *) path;
2473   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR,
2474         (xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args);
2475   if (serial == -1)
2476     return -1;
2477
2478   guestfs__switch_to_receiving (g);
2479   ctx.cb_sequence = 0;
2480   guestfs_set_reply_callback (g, mkdir_reply_cb, &ctx);
2481   (void) ml->main_loop_run (ml, g);
2482   guestfs_set_reply_callback (g, NULL, NULL);
2483   if (ctx.cb_sequence != 1001) {
2484     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir");
2485     return -1;
2486   }
2487
2488   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR, serial) == -1)
2489     return -1;
2490
2491   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2492     error (g, "%s", ctx.err.error_message);
2493     return -1;
2494   }
2495
2496   return 0;
2497 }
2498
2499 struct mkdir_p_ctx {
2500   /* This flag is set by the callbacks, so we know we've done
2501    * the callbacks as expected, and in the right sequence.
2502    * 0 = not called, 1 = send called,
2503    * 1001 = reply called.
2504    */
2505   int cb_sequence;
2506   struct guestfs_message_header hdr;
2507   struct guestfs_message_error err;
2508 };
2509
2510 static void mkdir_p_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2511 {
2512   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2513   struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data;
2514
2515   ml->main_loop_quit (ml, g);
2516
2517   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2518     error (g, "%s: failed to parse reply header", "guestfs_mkdir_p");
2519     return;
2520   }
2521   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2522     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2523       error (g, "%s: failed to parse reply error", "guestfs_mkdir_p");
2524       return;
2525     }
2526     goto done;
2527   }
2528  done:
2529   ctx->cb_sequence = 1001;
2530 }
2531
2532 int guestfs_mkdir_p (guestfs_h *g,
2533                 const char *path)
2534 {
2535   struct guestfs_mkdir_p_args args;
2536   struct mkdir_p_ctx ctx;
2537   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2538   int serial;
2539
2540   if (check_state (g, "guestfs_mkdir_p") == -1) return -1;
2541
2542   memset (&ctx, 0, sizeof ctx);
2543
2544   args.path = (char *) path;
2545   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR_P,
2546         (xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args);
2547   if (serial == -1)
2548     return -1;
2549
2550   guestfs__switch_to_receiving (g);
2551   ctx.cb_sequence = 0;
2552   guestfs_set_reply_callback (g, mkdir_p_reply_cb, &ctx);
2553   (void) ml->main_loop_run (ml, g);
2554   guestfs_set_reply_callback (g, NULL, NULL);
2555   if (ctx.cb_sequence != 1001) {
2556     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p");
2557     return -1;
2558   }
2559
2560   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1)
2561     return -1;
2562
2563   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2564     error (g, "%s", ctx.err.error_message);
2565     return -1;
2566   }
2567
2568   return 0;
2569 }
2570
2571 struct chmod_ctx {
2572   /* This flag is set by the callbacks, so we know we've done
2573    * the callbacks as expected, and in the right sequence.
2574    * 0 = not called, 1 = send called,
2575    * 1001 = reply called.
2576    */
2577   int cb_sequence;
2578   struct guestfs_message_header hdr;
2579   struct guestfs_message_error err;
2580 };
2581
2582 static void chmod_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2583 {
2584   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2585   struct chmod_ctx *ctx = (struct chmod_ctx *) data;
2586
2587   ml->main_loop_quit (ml, g);
2588
2589   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2590     error (g, "%s: failed to parse reply header", "guestfs_chmod");
2591     return;
2592   }
2593   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2594     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2595       error (g, "%s: failed to parse reply error", "guestfs_chmod");
2596       return;
2597     }
2598     goto done;
2599   }
2600  done:
2601   ctx->cb_sequence = 1001;
2602 }
2603
2604 int guestfs_chmod (guestfs_h *g,
2605                 int mode,
2606                 const char *path)
2607 {
2608   struct guestfs_chmod_args args;
2609   struct chmod_ctx ctx;
2610   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2611   int serial;
2612
2613   if (check_state (g, "guestfs_chmod") == -1) return -1;
2614
2615   memset (&ctx, 0, sizeof ctx);
2616
2617   args.mode = mode;
2618   args.path = (char *) path;
2619   serial = guestfs__send_sync (g, GUESTFS_PROC_CHMOD,
2620         (xdrproc_t) xdr_guestfs_chmod_args, (char *) &args);
2621   if (serial == -1)
2622     return -1;
2623
2624   guestfs__switch_to_receiving (g);
2625   ctx.cb_sequence = 0;
2626   guestfs_set_reply_callback (g, chmod_reply_cb, &ctx);
2627   (void) ml->main_loop_run (ml, g);
2628   guestfs_set_reply_callback (g, NULL, NULL);
2629   if (ctx.cb_sequence != 1001) {
2630     error (g, "%s reply failed, see earlier error messages", "guestfs_chmod");
2631     return -1;
2632   }
2633
2634   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHMOD, serial) == -1)
2635     return -1;
2636
2637   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2638     error (g, "%s", ctx.err.error_message);
2639     return -1;
2640   }
2641
2642   return 0;
2643 }
2644
2645 struct chown_ctx {
2646   /* This flag is set by the callbacks, so we know we've done
2647    * the callbacks as expected, and in the right sequence.
2648    * 0 = not called, 1 = send called,
2649    * 1001 = reply called.
2650    */
2651   int cb_sequence;
2652   struct guestfs_message_header hdr;
2653   struct guestfs_message_error err;
2654 };
2655
2656 static void chown_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2657 {
2658   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2659   struct chown_ctx *ctx = (struct chown_ctx *) data;
2660
2661   ml->main_loop_quit (ml, g);
2662
2663   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2664     error (g, "%s: failed to parse reply header", "guestfs_chown");
2665     return;
2666   }
2667   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2668     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2669       error (g, "%s: failed to parse reply error", "guestfs_chown");
2670       return;
2671     }
2672     goto done;
2673   }
2674  done:
2675   ctx->cb_sequence = 1001;
2676 }
2677
2678 int guestfs_chown (guestfs_h *g,
2679                 int owner,
2680                 int group,
2681                 const char *path)
2682 {
2683   struct guestfs_chown_args args;
2684   struct chown_ctx ctx;
2685   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2686   int serial;
2687
2688   if (check_state (g, "guestfs_chown") == -1) return -1;
2689
2690   memset (&ctx, 0, sizeof ctx);
2691
2692   args.owner = owner;
2693   args.group = group;
2694   args.path = (char *) path;
2695   serial = guestfs__send_sync (g, GUESTFS_PROC_CHOWN,
2696         (xdrproc_t) xdr_guestfs_chown_args, (char *) &args);
2697   if (serial == -1)
2698     return -1;
2699
2700   guestfs__switch_to_receiving (g);
2701   ctx.cb_sequence = 0;
2702   guestfs_set_reply_callback (g, chown_reply_cb, &ctx);
2703   (void) ml->main_loop_run (ml, g);
2704   guestfs_set_reply_callback (g, NULL, NULL);
2705   if (ctx.cb_sequence != 1001) {
2706     error (g, "%s reply failed, see earlier error messages", "guestfs_chown");
2707     return -1;
2708   }
2709
2710   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHOWN, serial) == -1)
2711     return -1;
2712
2713   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2714     error (g, "%s", ctx.err.error_message);
2715     return -1;
2716   }
2717
2718   return 0;
2719 }
2720
2721 struct exists_ctx {
2722   /* This flag is set by the callbacks, so we know we've done
2723    * the callbacks as expected, and in the right sequence.
2724    * 0 = not called, 1 = send called,
2725    * 1001 = reply called.
2726    */
2727   int cb_sequence;
2728   struct guestfs_message_header hdr;
2729   struct guestfs_message_error err;
2730   struct guestfs_exists_ret ret;
2731 };
2732
2733 static void exists_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2734 {
2735   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2736   struct exists_ctx *ctx = (struct exists_ctx *) data;
2737
2738   ml->main_loop_quit (ml, g);
2739
2740   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2741     error (g, "%s: failed to parse reply header", "guestfs_exists");
2742     return;
2743   }
2744   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2745     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2746       error (g, "%s: failed to parse reply error", "guestfs_exists");
2747       return;
2748     }
2749     goto done;
2750   }
2751   if (!xdr_guestfs_exists_ret (xdr, &ctx->ret)) {
2752     error (g, "%s: failed to parse reply", "guestfs_exists");
2753     return;
2754   }
2755  done:
2756   ctx->cb_sequence = 1001;
2757 }
2758
2759 int guestfs_exists (guestfs_h *g,
2760                 const char *path)
2761 {
2762   struct guestfs_exists_args args;
2763   struct exists_ctx ctx;
2764   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2765   int serial;
2766
2767   if (check_state (g, "guestfs_exists") == -1) return -1;
2768
2769   memset (&ctx, 0, sizeof ctx);
2770
2771   args.path = (char *) path;
2772   serial = guestfs__send_sync (g, GUESTFS_PROC_EXISTS,
2773         (xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
2774   if (serial == -1)
2775     return -1;
2776
2777   guestfs__switch_to_receiving (g);
2778   ctx.cb_sequence = 0;
2779   guestfs_set_reply_callback (g, exists_reply_cb, &ctx);
2780   (void) ml->main_loop_run (ml, g);
2781   guestfs_set_reply_callback (g, NULL, NULL);
2782   if (ctx.cb_sequence != 1001) {
2783     error (g, "%s reply failed, see earlier error messages", "guestfs_exists");
2784     return -1;
2785   }
2786
2787   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EXISTS, serial) == -1)
2788     return -1;
2789
2790   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2791     error (g, "%s", ctx.err.error_message);
2792     return -1;
2793   }
2794
2795   return ctx.ret.existsflag;
2796 }
2797
2798 struct is_file_ctx {
2799   /* This flag is set by the callbacks, so we know we've done
2800    * the callbacks as expected, and in the right sequence.
2801    * 0 = not called, 1 = send called,
2802    * 1001 = reply called.
2803    */
2804   int cb_sequence;
2805   struct guestfs_message_header hdr;
2806   struct guestfs_message_error err;
2807   struct guestfs_is_file_ret ret;
2808 };
2809
2810 static void is_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2811 {
2812   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2813   struct is_file_ctx *ctx = (struct is_file_ctx *) data;
2814
2815   ml->main_loop_quit (ml, g);
2816
2817   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2818     error (g, "%s: failed to parse reply header", "guestfs_is_file");
2819     return;
2820   }
2821   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2822     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2823       error (g, "%s: failed to parse reply error", "guestfs_is_file");
2824       return;
2825     }
2826     goto done;
2827   }
2828   if (!xdr_guestfs_is_file_ret (xdr, &ctx->ret)) {
2829     error (g, "%s: failed to parse reply", "guestfs_is_file");
2830     return;
2831   }
2832  done:
2833   ctx->cb_sequence = 1001;
2834 }
2835
2836 int guestfs_is_file (guestfs_h *g,
2837                 const char *path)
2838 {
2839   struct guestfs_is_file_args args;
2840   struct is_file_ctx ctx;
2841   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2842   int serial;
2843
2844   if (check_state (g, "guestfs_is_file") == -1) return -1;
2845
2846   memset (&ctx, 0, sizeof ctx);
2847
2848   args.path = (char *) path;
2849   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_FILE,
2850         (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
2851   if (serial == -1)
2852     return -1;
2853
2854   guestfs__switch_to_receiving (g);
2855   ctx.cb_sequence = 0;
2856   guestfs_set_reply_callback (g, is_file_reply_cb, &ctx);
2857   (void) ml->main_loop_run (ml, g);
2858   guestfs_set_reply_callback (g, NULL, NULL);
2859   if (ctx.cb_sequence != 1001) {
2860     error (g, "%s reply failed, see earlier error messages", "guestfs_is_file");
2861     return -1;
2862   }
2863
2864   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_FILE, serial) == -1)
2865     return -1;
2866
2867   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2868     error (g, "%s", ctx.err.error_message);
2869     return -1;
2870   }
2871
2872   return ctx.ret.fileflag;
2873 }
2874
2875 struct is_dir_ctx {
2876   /* This flag is set by the callbacks, so we know we've done
2877    * the callbacks as expected, and in the right sequence.
2878    * 0 = not called, 1 = send called,
2879    * 1001 = reply called.
2880    */
2881   int cb_sequence;
2882   struct guestfs_message_header hdr;
2883   struct guestfs_message_error err;
2884   struct guestfs_is_dir_ret ret;
2885 };
2886
2887 static void is_dir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2888 {
2889   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2890   struct is_dir_ctx *ctx = (struct is_dir_ctx *) data;
2891
2892   ml->main_loop_quit (ml, g);
2893
2894   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2895     error (g, "%s: failed to parse reply header", "guestfs_is_dir");
2896     return;
2897   }
2898   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2899     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2900       error (g, "%s: failed to parse reply error", "guestfs_is_dir");
2901       return;
2902     }
2903     goto done;
2904   }
2905   if (!xdr_guestfs_is_dir_ret (xdr, &ctx->ret)) {
2906     error (g, "%s: failed to parse reply", "guestfs_is_dir");
2907     return;
2908   }
2909  done:
2910   ctx->cb_sequence = 1001;
2911 }
2912
2913 int guestfs_is_dir (guestfs_h *g,
2914                 const char *path)
2915 {
2916   struct guestfs_is_dir_args args;
2917   struct is_dir_ctx ctx;
2918   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2919   int serial;
2920
2921   if (check_state (g, "guestfs_is_dir") == -1) return -1;
2922
2923   memset (&ctx, 0, sizeof ctx);
2924
2925   args.path = (char *) path;
2926   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_DIR,
2927         (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
2928   if (serial == -1)
2929     return -1;
2930
2931   guestfs__switch_to_receiving (g);
2932   ctx.cb_sequence = 0;
2933   guestfs_set_reply_callback (g, is_dir_reply_cb, &ctx);
2934   (void) ml->main_loop_run (ml, g);
2935   guestfs_set_reply_callback (g, NULL, NULL);
2936   if (ctx.cb_sequence != 1001) {
2937     error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir");
2938     return -1;
2939   }
2940
2941   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_DIR, serial) == -1)
2942     return -1;
2943
2944   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2945     error (g, "%s", ctx.err.error_message);
2946     return -1;
2947   }
2948
2949   return ctx.ret.dirflag;
2950 }
2951
2952 struct pvcreate_ctx {
2953   /* This flag is set by the callbacks, so we know we've done
2954    * the callbacks as expected, and in the right sequence.
2955    * 0 = not called, 1 = send called,
2956    * 1001 = reply called.
2957    */
2958   int cb_sequence;
2959   struct guestfs_message_header hdr;
2960   struct guestfs_message_error err;
2961 };
2962
2963 static void pvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2964 {
2965   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2966   struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data;
2967
2968   ml->main_loop_quit (ml, g);
2969
2970   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2971     error (g, "%s: failed to parse reply header", "guestfs_pvcreate");
2972     return;
2973   }
2974   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2975     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2976       error (g, "%s: failed to parse reply error", "guestfs_pvcreate");
2977       return;
2978     }
2979     goto done;
2980   }
2981  done:
2982   ctx->cb_sequence = 1001;
2983 }
2984
2985 int guestfs_pvcreate (guestfs_h *g,
2986                 const char *device)
2987 {
2988   struct guestfs_pvcreate_args args;
2989   struct pvcreate_ctx ctx;
2990   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2991   int serial;
2992
2993   if (check_state (g, "guestfs_pvcreate") == -1) return -1;
2994
2995   memset (&ctx, 0, sizeof ctx);
2996
2997   args.device = (char *) device;
2998   serial = guestfs__send_sync (g, GUESTFS_PROC_PVCREATE,
2999         (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
3000   if (serial == -1)
3001     return -1;
3002
3003   guestfs__switch_to_receiving (g);
3004   ctx.cb_sequence = 0;
3005   guestfs_set_reply_callback (g, pvcreate_reply_cb, &ctx);
3006   (void) ml->main_loop_run (ml, g);
3007   guestfs_set_reply_callback (g, NULL, NULL);
3008   if (ctx.cb_sequence != 1001) {
3009     error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate");
3010     return -1;
3011   }
3012
3013   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVCREATE, serial) == -1)
3014     return -1;
3015
3016   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3017     error (g, "%s", ctx.err.error_message);
3018     return -1;
3019   }
3020
3021   return 0;
3022 }
3023
3024 struct vgcreate_ctx {
3025   /* This flag is set by the callbacks, so we know we've done
3026    * the callbacks as expected, and in the right sequence.
3027    * 0 = not called, 1 = send called,
3028    * 1001 = reply called.
3029    */
3030   int cb_sequence;
3031   struct guestfs_message_header hdr;
3032   struct guestfs_message_error err;
3033 };
3034
3035 static void vgcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3036 {
3037   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3038   struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data;
3039
3040   ml->main_loop_quit (ml, g);
3041
3042   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3043     error (g, "%s: failed to parse reply header", "guestfs_vgcreate");
3044     return;
3045   }
3046   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3047     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3048       error (g, "%s: failed to parse reply error", "guestfs_vgcreate");
3049       return;
3050     }
3051     goto done;
3052   }
3053  done:
3054   ctx->cb_sequence = 1001;
3055 }
3056
3057 int guestfs_vgcreate (guestfs_h *g,
3058                 const char *volgroup,
3059                 char * const* const physvols)
3060 {
3061   struct guestfs_vgcreate_args args;
3062   struct vgcreate_ctx ctx;
3063   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3064   int serial;
3065
3066   if (check_state (g, "guestfs_vgcreate") == -1) return -1;
3067
3068   memset (&ctx, 0, sizeof ctx);
3069
3070   args.volgroup = (char *) volgroup;
3071   args.physvols.physvols_val = (char **) physvols;
3072   for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ;
3073   serial = guestfs__send_sync (g, GUESTFS_PROC_VGCREATE,
3074         (xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
3075   if (serial == -1)
3076     return -1;
3077
3078   guestfs__switch_to_receiving (g);
3079   ctx.cb_sequence = 0;
3080   guestfs_set_reply_callback (g, vgcreate_reply_cb, &ctx);
3081   (void) ml->main_loop_run (ml, g);
3082   guestfs_set_reply_callback (g, NULL, NULL);
3083   if (ctx.cb_sequence != 1001) {
3084     error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate");
3085     return -1;
3086   }
3087
3088   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGCREATE, serial) == -1)
3089     return -1;
3090
3091   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3092     error (g, "%s", ctx.err.error_message);
3093     return -1;
3094   }
3095
3096   return 0;
3097 }
3098
3099 struct lvcreate_ctx {
3100   /* This flag is set by the callbacks, so we know we've done
3101    * the callbacks as expected, and in the right sequence.
3102    * 0 = not called, 1 = send called,
3103    * 1001 = reply called.
3104    */
3105   int cb_sequence;
3106   struct guestfs_message_header hdr;
3107   struct guestfs_message_error err;
3108 };
3109
3110 static void lvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3111 {
3112   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3113   struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data;
3114
3115   ml->main_loop_quit (ml, g);
3116
3117   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3118     error (g, "%s: failed to parse reply header", "guestfs_lvcreate");
3119     return;
3120   }
3121   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3122     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3123       error (g, "%s: failed to parse reply error", "guestfs_lvcreate");
3124       return;
3125     }
3126     goto done;
3127   }
3128  done:
3129   ctx->cb_sequence = 1001;
3130 }
3131
3132 int guestfs_lvcreate (guestfs_h *g,
3133                 const char *logvol,
3134                 const char *volgroup,
3135                 int mbytes)
3136 {
3137   struct guestfs_lvcreate_args args;
3138   struct lvcreate_ctx ctx;
3139   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3140   int serial;
3141
3142   if (check_state (g, "guestfs_lvcreate") == -1) return -1;
3143
3144   memset (&ctx, 0, sizeof ctx);
3145
3146   args.logvol = (char *) logvol;
3147   args.volgroup = (char *) volgroup;
3148   args.mbytes = mbytes;
3149   serial = guestfs__send_sync (g, GUESTFS_PROC_LVCREATE,
3150         (xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
3151   if (serial == -1)
3152     return -1;
3153
3154   guestfs__switch_to_receiving (g);
3155   ctx.cb_sequence = 0;
3156   guestfs_set_reply_callback (g, lvcreate_reply_cb, &ctx);
3157   (void) ml->main_loop_run (ml, g);
3158   guestfs_set_reply_callback (g, NULL, NULL);
3159   if (ctx.cb_sequence != 1001) {
3160     error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate");
3161     return -1;
3162   }
3163
3164   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVCREATE, serial) == -1)
3165     return -1;
3166
3167   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3168     error (g, "%s", ctx.err.error_message);
3169     return -1;
3170   }
3171
3172   return 0;
3173 }
3174
3175 struct mkfs_ctx {
3176   /* This flag is set by the callbacks, so we know we've done
3177    * the callbacks as expected, and in the right sequence.
3178    * 0 = not called, 1 = send called,
3179    * 1001 = reply called.
3180    */
3181   int cb_sequence;
3182   struct guestfs_message_header hdr;
3183   struct guestfs_message_error err;
3184 };
3185
3186 static void mkfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3187 {
3188   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3189   struct mkfs_ctx *ctx = (struct mkfs_ctx *) data;
3190
3191   ml->main_loop_quit (ml, g);
3192
3193   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3194     error (g, "%s: failed to parse reply header", "guestfs_mkfs");
3195     return;
3196   }
3197   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3198     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3199       error (g, "%s: failed to parse reply error", "guestfs_mkfs");
3200       return;
3201     }
3202     goto done;
3203   }
3204  done:
3205   ctx->cb_sequence = 1001;
3206 }
3207
3208 int guestfs_mkfs (guestfs_h *g,
3209                 const char *fstype,
3210                 const char *device)
3211 {
3212   struct guestfs_mkfs_args args;
3213   struct mkfs_ctx ctx;
3214   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3215   int serial;
3216
3217   if (check_state (g, "guestfs_mkfs") == -1) return -1;
3218
3219   memset (&ctx, 0, sizeof ctx);
3220
3221   args.fstype = (char *) fstype;
3222   args.device = (char *) device;
3223   serial = guestfs__send_sync (g, GUESTFS_PROC_MKFS,
3224         (xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
3225   if (serial == -1)
3226     return -1;
3227
3228   guestfs__switch_to_receiving (g);
3229   ctx.cb_sequence = 0;
3230   guestfs_set_reply_callback (g, mkfs_reply_cb, &ctx);
3231   (void) ml->main_loop_run (ml, g);
3232   guestfs_set_reply_callback (g, NULL, NULL);
3233   if (ctx.cb_sequence != 1001) {
3234     error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs");
3235     return -1;
3236   }
3237
3238   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFS, serial) == -1)
3239     return -1;
3240
3241   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3242     error (g, "%s", ctx.err.error_message);
3243     return -1;
3244   }
3245
3246   return 0;
3247 }
3248
3249 struct sfdisk_ctx {
3250   /* This flag is set by the callbacks, so we know we've done
3251    * the callbacks as expected, and in the right sequence.
3252    * 0 = not called, 1 = send called,
3253    * 1001 = reply called.
3254    */
3255   int cb_sequence;
3256   struct guestfs_message_header hdr;
3257   struct guestfs_message_error err;
3258 };
3259
3260 static void sfdisk_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3261 {
3262   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3263   struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data;
3264
3265   ml->main_loop_quit (ml, g);
3266
3267   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3268     error (g, "%s: failed to parse reply header", "guestfs_sfdisk");
3269     return;
3270   }
3271   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3272     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3273       error (g, "%s: failed to parse reply error", "guestfs_sfdisk");
3274       return;
3275     }
3276     goto done;
3277   }
3278  done:
3279   ctx->cb_sequence = 1001;
3280 }
3281
3282 int guestfs_sfdisk (guestfs_h *g,
3283                 const char *device,
3284                 int cyls,
3285                 int heads,
3286                 int sectors,
3287                 char * const* const lines)
3288 {
3289   struct guestfs_sfdisk_args args;
3290   struct sfdisk_ctx ctx;
3291   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3292   int serial;
3293
3294   if (check_state (g, "guestfs_sfdisk") == -1) return -1;
3295
3296   memset (&ctx, 0, sizeof ctx);
3297
3298   args.device = (char *) device;
3299   args.cyls = cyls;
3300   args.heads = heads;
3301   args.sectors = sectors;
3302   args.lines.lines_val = (char **) lines;
3303   for (args.lines.lines_len = 0; lines[args.lines.lines_len]; args.lines.lines_len++) ;
3304   serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK,
3305         (xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
3306   if (serial == -1)
3307     return -1;
3308
3309   guestfs__switch_to_receiving (g);
3310   ctx.cb_sequence = 0;
3311   guestfs_set_reply_callback (g, sfdisk_reply_cb, &ctx);
3312   (void) ml->main_loop_run (ml, g);
3313   guestfs_set_reply_callback (g, NULL, NULL);
3314   if (ctx.cb_sequence != 1001) {
3315     error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk");
3316     return -1;
3317   }
3318
3319   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK, serial) == -1)
3320     return -1;
3321
3322   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3323     error (g, "%s", ctx.err.error_message);
3324     return -1;
3325   }
3326
3327   return 0;
3328 }
3329
3330 struct write_file_ctx {
3331   /* This flag is set by the callbacks, so we know we've done
3332    * the callbacks as expected, and in the right sequence.
3333    * 0 = not called, 1 = send called,
3334    * 1001 = reply called.
3335    */
3336   int cb_sequence;
3337   struct guestfs_message_header hdr;
3338   struct guestfs_message_error err;
3339 };
3340
3341 static void write_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3342 {
3343   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3344   struct write_file_ctx *ctx = (struct write_file_ctx *) data;
3345
3346   ml->main_loop_quit (ml, g);
3347
3348   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3349     error (g, "%s: failed to parse reply header", "guestfs_write_file");
3350     return;
3351   }
3352   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3353     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3354       error (g, "%s: failed to parse reply error", "guestfs_write_file");
3355       return;
3356     }
3357     goto done;
3358   }
3359  done:
3360   ctx->cb_sequence = 1001;
3361 }
3362
3363 int guestfs_write_file (guestfs_h *g,
3364                 const char *path,
3365                 const char *content,
3366                 int size)
3367 {
3368   struct guestfs_write_file_args args;
3369   struct write_file_ctx ctx;
3370   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3371   int serial;
3372
3373   if (check_state (g, "guestfs_write_file") == -1) return -1;
3374
3375   memset (&ctx, 0, sizeof ctx);
3376
3377   args.path = (char *) path;
3378   args.content = (char *) content;
3379   args.size = size;
3380   serial = guestfs__send_sync (g, GUESTFS_PROC_WRITE_FILE,
3381         (xdrproc_t) xdr_guestfs_write_file_args, (char *) &args);
3382   if (serial == -1)
3383     return -1;
3384
3385   guestfs__switch_to_receiving (g);
3386   ctx.cb_sequence = 0;
3387   guestfs_set_reply_callback (g, write_file_reply_cb, &ctx);
3388   (void) ml->main_loop_run (ml, g);
3389   guestfs_set_reply_callback (g, NULL, NULL);
3390   if (ctx.cb_sequence != 1001) {
3391     error (g, "%s reply failed, see earlier error messages", "guestfs_write_file");
3392     return -1;
3393   }
3394
3395   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1)
3396     return -1;
3397
3398   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3399     error (g, "%s", ctx.err.error_message);
3400     return -1;
3401   }
3402
3403   return 0;
3404 }
3405
3406 struct umount_ctx {
3407   /* This flag is set by the callbacks, so we know we've done
3408    * the callbacks as expected, and in the right sequence.
3409    * 0 = not called, 1 = send called,
3410    * 1001 = reply called.
3411    */
3412   int cb_sequence;
3413   struct guestfs_message_header hdr;
3414   struct guestfs_message_error err;
3415 };
3416
3417 static void umount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3418 {
3419   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3420   struct umount_ctx *ctx = (struct umount_ctx *) data;
3421
3422   ml->main_loop_quit (ml, g);
3423
3424   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3425     error (g, "%s: failed to parse reply header", "guestfs_umount");
3426     return;
3427   }
3428   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3429     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3430       error (g, "%s: failed to parse reply error", "guestfs_umount");
3431       return;
3432     }
3433     goto done;
3434   }
3435  done:
3436   ctx->cb_sequence = 1001;
3437 }
3438
3439 int guestfs_umount (guestfs_h *g,
3440                 const char *pathordevice)
3441 {
3442   struct guestfs_umount_args args;
3443   struct umount_ctx ctx;
3444   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3445   int serial;
3446
3447   if (check_state (g, "guestfs_umount") == -1) return -1;
3448
3449   memset (&ctx, 0, sizeof ctx);
3450
3451   args.pathordevice = (char *) pathordevice;
3452   serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT,
3453         (xdrproc_t) xdr_guestfs_umount_args, (char *) &args);
3454   if (serial == -1)
3455     return -1;
3456
3457   guestfs__switch_to_receiving (g);
3458   ctx.cb_sequence = 0;
3459   guestfs_set_reply_callback (g, umount_reply_cb, &ctx);
3460   (void) ml->main_loop_run (ml, g);
3461   guestfs_set_reply_callback (g, NULL, NULL);
3462   if (ctx.cb_sequence != 1001) {
3463     error (g, "%s reply failed, see earlier error messages", "guestfs_umount");
3464     return -1;
3465   }
3466
3467   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT, serial) == -1)
3468     return -1;
3469
3470   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3471     error (g, "%s", ctx.err.error_message);
3472     return -1;
3473   }
3474
3475   return 0;
3476 }
3477
3478 struct mounts_ctx {
3479   /* This flag is set by the callbacks, so we know we've done
3480    * the callbacks as expected, and in the right sequence.
3481    * 0 = not called, 1 = send called,
3482    * 1001 = reply called.
3483    */
3484   int cb_sequence;
3485   struct guestfs_message_header hdr;
3486   struct guestfs_message_error err;
3487   struct guestfs_mounts_ret ret;
3488 };
3489
3490 static void mounts_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3491 {
3492   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3493   struct mounts_ctx *ctx = (struct mounts_ctx *) data;
3494
3495   ml->main_loop_quit (ml, g);
3496
3497   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3498     error (g, "%s: failed to parse reply header", "guestfs_mounts");
3499     return;
3500   }
3501   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3502     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3503       error (g, "%s: failed to parse reply error", "guestfs_mounts");
3504       return;
3505     }
3506     goto done;
3507   }
3508   if (!xdr_guestfs_mounts_ret (xdr, &ctx->ret)) {
3509     error (g, "%s: failed to parse reply", "guestfs_mounts");
3510     return;
3511   }
3512  done:
3513   ctx->cb_sequence = 1001;
3514 }
3515
3516 char **guestfs_mounts (guestfs_h *g)
3517 {
3518   struct mounts_ctx ctx;
3519   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3520   int serial;
3521
3522   if (check_state (g, "guestfs_mounts") == -1) return NULL;
3523
3524   memset (&ctx, 0, sizeof ctx);
3525
3526   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
3527   if (serial == -1)
3528     return NULL;
3529
3530   guestfs__switch_to_receiving (g);
3531   ctx.cb_sequence = 0;
3532   guestfs_set_reply_callback (g, mounts_reply_cb, &ctx);
3533   (void) ml->main_loop_run (ml, g);
3534   guestfs_set_reply_callback (g, NULL, NULL);
3535   if (ctx.cb_sequence != 1001) {
3536     error (g, "%s reply failed, see earlier error messages", "guestfs_mounts");
3537     return NULL;
3538   }
3539
3540   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNTS, serial) == -1)
3541     return NULL;
3542
3543   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3544     error (g, "%s", ctx.err.error_message);
3545     return NULL;
3546   }
3547
3548   /* caller will free this, but we need to add a NULL entry */
3549   ctx.ret.devices.devices_val =
3550     safe_realloc (g, ctx.ret.devices.devices_val,
3551                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
3552   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
3553   return ctx.ret.devices.devices_val;
3554 }
3555
3556 struct umount_all_ctx {
3557   /* This flag is set by the callbacks, so we know we've done
3558    * the callbacks as expected, and in the right sequence.
3559    * 0 = not called, 1 = send called,
3560    * 1001 = reply called.
3561    */
3562   int cb_sequence;
3563   struct guestfs_message_header hdr;
3564   struct guestfs_message_error err;
3565 };
3566
3567 static void umount_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3568 {
3569   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3570   struct umount_all_ctx *ctx = (struct umount_all_ctx *) data;
3571
3572   ml->main_loop_quit (ml, g);
3573
3574   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3575     error (g, "%s: failed to parse reply header", "guestfs_umount_all");
3576     return;
3577   }
3578   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3579     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3580       error (g, "%s: failed to parse reply error", "guestfs_umount_all");
3581       return;
3582     }
3583     goto done;
3584   }
3585  done:
3586   ctx->cb_sequence = 1001;
3587 }
3588
3589 int guestfs_umount_all (guestfs_h *g)
3590 {
3591   struct umount_all_ctx ctx;
3592   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3593   int serial;
3594
3595   if (check_state (g, "guestfs_umount_all") == -1) return -1;
3596
3597   memset (&ctx, 0, sizeof ctx);
3598
3599   serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
3600   if (serial == -1)
3601     return -1;
3602
3603   guestfs__switch_to_receiving (g);
3604   ctx.cb_sequence = 0;
3605   guestfs_set_reply_callback (g, umount_all_reply_cb, &ctx);
3606   (void) ml->main_loop_run (ml, g);
3607   guestfs_set_reply_callback (g, NULL, NULL);
3608   if (ctx.cb_sequence != 1001) {
3609     error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all");
3610     return -1;
3611   }
3612
3613   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1)
3614     return -1;
3615
3616   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3617     error (g, "%s", ctx.err.error_message);
3618     return -1;
3619   }
3620
3621   return 0;
3622 }
3623
3624 struct lvm_remove_all_ctx {
3625   /* This flag is set by the callbacks, so we know we've done
3626    * the callbacks as expected, and in the right sequence.
3627    * 0 = not called, 1 = send called,
3628    * 1001 = reply called.
3629    */
3630   int cb_sequence;
3631   struct guestfs_message_header hdr;
3632   struct guestfs_message_error err;
3633 };
3634
3635 static void lvm_remove_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3636 {
3637   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3638   struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data;
3639
3640   ml->main_loop_quit (ml, g);
3641
3642   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3643     error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all");
3644     return;
3645   }
3646   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3647     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3648       error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all");
3649       return;
3650     }
3651     goto done;
3652   }
3653  done:
3654   ctx->cb_sequence = 1001;
3655 }
3656
3657 int guestfs_lvm_remove_all (guestfs_h *g)
3658 {
3659   struct lvm_remove_all_ctx ctx;
3660   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3661   int serial;
3662
3663   if (check_state (g, "guestfs_lvm_remove_all") == -1) return -1;
3664
3665   memset (&ctx, 0, sizeof ctx);
3666
3667   serial = guestfs__send_sync (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
3668   if (serial == -1)
3669     return -1;
3670
3671   guestfs__switch_to_receiving (g);
3672   ctx.cb_sequence = 0;
3673   guestfs_set_reply_callback (g, lvm_remove_all_reply_cb, &ctx);
3674   (void) ml->main_loop_run (ml, g);
3675   guestfs_set_reply_callback (g, NULL, NULL);
3676   if (ctx.cb_sequence != 1001) {
3677     error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all");
3678     return -1;
3679   }
3680
3681   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1)
3682     return -1;
3683
3684   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3685     error (g, "%s", ctx.err.error_message);
3686     return -1;
3687   }
3688
3689   return 0;
3690 }
3691
3692 struct file_ctx {
3693   /* This flag is set by the callbacks, so we know we've done
3694    * the callbacks as expected, and in the right sequence.
3695    * 0 = not called, 1 = send called,
3696    * 1001 = reply called.
3697    */
3698   int cb_sequence;
3699   struct guestfs_message_header hdr;
3700   struct guestfs_message_error err;
3701   struct guestfs_file_ret ret;
3702 };
3703
3704 static void file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3705 {
3706   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3707   struct file_ctx *ctx = (struct file_ctx *) data;
3708
3709   ml->main_loop_quit (ml, g);
3710
3711   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3712     error (g, "%s: failed to parse reply header", "guestfs_file");
3713     return;
3714   }
3715   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3716     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3717       error (g, "%s: failed to parse reply error", "guestfs_file");
3718       return;
3719     }
3720     goto done;
3721   }
3722   if (!xdr_guestfs_file_ret (xdr, &ctx->ret)) {
3723     error (g, "%s: failed to parse reply", "guestfs_file");
3724     return;
3725   }
3726  done:
3727   ctx->cb_sequence = 1001;
3728 }
3729
3730 char *guestfs_file (guestfs_h *g,
3731                 const char *path)
3732 {
3733   struct guestfs_file_args args;
3734   struct file_ctx ctx;
3735   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3736   int serial;
3737
3738   if (check_state (g, "guestfs_file") == -1) return NULL;
3739
3740   memset (&ctx, 0, sizeof ctx);
3741
3742   args.path = (char *) path;
3743   serial = guestfs__send_sync (g, GUESTFS_PROC_FILE,
3744         (xdrproc_t) xdr_guestfs_file_args, (char *) &args);
3745   if (serial == -1)
3746     return NULL;
3747
3748   guestfs__switch_to_receiving (g);
3749   ctx.cb_sequence = 0;
3750   guestfs_set_reply_callback (g, file_reply_cb, &ctx);
3751   (void) ml->main_loop_run (ml, g);
3752   guestfs_set_reply_callback (g, NULL, NULL);
3753   if (ctx.cb_sequence != 1001) {
3754     error (g, "%s reply failed, see earlier error messages", "guestfs_file");
3755     return NULL;
3756   }
3757
3758   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FILE, serial) == -1)
3759     return NULL;
3760
3761   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3762     error (g, "%s", ctx.err.error_message);
3763     return NULL;
3764   }
3765
3766   return ctx.ret.description; /* caller will free */
3767 }
3768
3769 struct command_ctx {
3770   /* This flag is set by the callbacks, so we know we've done
3771    * the callbacks as expected, and in the right sequence.
3772    * 0 = not called, 1 = send called,
3773    * 1001 = reply called.
3774    */
3775   int cb_sequence;
3776   struct guestfs_message_header hdr;
3777   struct guestfs_message_error err;
3778   struct guestfs_command_ret ret;
3779 };
3780
3781 static void command_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3782 {
3783   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3784   struct command_ctx *ctx = (struct command_ctx *) data;
3785
3786   ml->main_loop_quit (ml, g);
3787
3788   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3789     error (g, "%s: failed to parse reply header", "guestfs_command");
3790     return;
3791   }
3792   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3793     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3794       error (g, "%s: failed to parse reply error", "guestfs_command");
3795       return;
3796     }
3797     goto done;
3798   }
3799   if (!xdr_guestfs_command_ret (xdr, &ctx->ret)) {
3800     error (g, "%s: failed to parse reply", "guestfs_command");
3801     return;
3802   }
3803  done:
3804   ctx->cb_sequence = 1001;
3805 }
3806
3807 char *guestfs_command (guestfs_h *g,
3808                 char * const* const arguments)
3809 {
3810   struct guestfs_command_args args;
3811   struct command_ctx ctx;
3812   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3813   int serial;
3814
3815   if (check_state (g, "guestfs_command") == -1) return NULL;
3816
3817   memset (&ctx, 0, sizeof ctx);
3818
3819   args.arguments.arguments_val = (char **) arguments;
3820   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
3821   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND,
3822         (xdrproc_t) xdr_guestfs_command_args, (char *) &args);
3823   if (serial == -1)
3824     return NULL;
3825
3826   guestfs__switch_to_receiving (g);
3827   ctx.cb_sequence = 0;
3828   guestfs_set_reply_callback (g, command_reply_cb, &ctx);
3829   (void) ml->main_loop_run (ml, g);
3830   guestfs_set_reply_callback (g, NULL, NULL);
3831   if (ctx.cb_sequence != 1001) {
3832     error (g, "%s reply failed, see earlier error messages", "guestfs_command");
3833     return NULL;
3834   }
3835
3836   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND, serial) == -1)
3837     return NULL;
3838
3839   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3840     error (g, "%s", ctx.err.error_message);
3841     return NULL;
3842   }
3843
3844   return ctx.ret.output; /* caller will free */
3845 }
3846
3847 struct command_lines_ctx {
3848   /* This flag is set by the callbacks, so we know we've done
3849    * the callbacks as expected, and in the right sequence.
3850    * 0 = not called, 1 = send called,
3851    * 1001 = reply called.
3852    */
3853   int cb_sequence;
3854   struct guestfs_message_header hdr;
3855   struct guestfs_message_error err;
3856   struct guestfs_command_lines_ret ret;
3857 };
3858
3859 static void command_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3860 {
3861   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3862   struct command_lines_ctx *ctx = (struct command_lines_ctx *) data;
3863
3864   ml->main_loop_quit (ml, g);
3865
3866   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3867     error (g, "%s: failed to parse reply header", "guestfs_command_lines");
3868     return;
3869   }
3870   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3871     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3872       error (g, "%s: failed to parse reply error", "guestfs_command_lines");
3873       return;
3874     }
3875     goto done;
3876   }
3877   if (!xdr_guestfs_command_lines_ret (xdr, &ctx->ret)) {
3878     error (g, "%s: failed to parse reply", "guestfs_command_lines");
3879     return;
3880   }
3881  done:
3882   ctx->cb_sequence = 1001;
3883 }
3884
3885 char **guestfs_command_lines (guestfs_h *g,
3886                 char * const* const arguments)
3887 {
3888   struct guestfs_command_lines_args args;
3889   struct command_lines_ctx ctx;
3890   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3891   int serial;
3892
3893   if (check_state (g, "guestfs_command_lines") == -1) return NULL;
3894
3895   memset (&ctx, 0, sizeof ctx);
3896
3897   args.arguments.arguments_val = (char **) arguments;
3898   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
3899   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND_LINES,
3900         (xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args);
3901   if (serial == -1)
3902     return NULL;
3903
3904   guestfs__switch_to_receiving (g);
3905   ctx.cb_sequence = 0;
3906   guestfs_set_reply_callback (g, command_lines_reply_cb, &ctx);
3907   (void) ml->main_loop_run (ml, g);
3908   guestfs_set_reply_callback (g, NULL, NULL);
3909   if (ctx.cb_sequence != 1001) {
3910     error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines");
3911     return NULL;
3912   }
3913
3914   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1)
3915     return NULL;
3916
3917   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3918     error (g, "%s", ctx.err.error_message);
3919     return NULL;
3920   }
3921
3922   /* caller will free this, but we need to add a NULL entry */
3923   ctx.ret.lines.lines_val =
3924     safe_realloc (g, ctx.ret.lines.lines_val,
3925                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
3926   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
3927   return ctx.ret.lines.lines_val;
3928 }
3929
3930 struct stat_ctx {
3931   /* This flag is set by the callbacks, so we know we've done
3932    * the callbacks as expected, and in the right sequence.
3933    * 0 = not called, 1 = send called,
3934    * 1001 = reply called.
3935    */
3936   int cb_sequence;
3937   struct guestfs_message_header hdr;
3938   struct guestfs_message_error err;
3939   struct guestfs_stat_ret ret;
3940 };
3941
3942 static void stat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3943 {
3944   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3945   struct stat_ctx *ctx = (struct stat_ctx *) data;
3946
3947   ml->main_loop_quit (ml, g);
3948
3949   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3950     error (g, "%s: failed to parse reply header", "guestfs_stat");
3951     return;
3952   }
3953   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3954     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3955       error (g, "%s: failed to parse reply error", "guestfs_stat");
3956       return;
3957     }
3958     goto done;
3959   }
3960   if (!xdr_guestfs_stat_ret (xdr, &ctx->ret)) {
3961     error (g, "%s: failed to parse reply", "guestfs_stat");
3962     return;
3963   }
3964  done:
3965   ctx->cb_sequence = 1001;
3966 }
3967
3968 struct guestfs_stat *guestfs_stat (guestfs_h *g,
3969                 const char *path)
3970 {
3971   struct guestfs_stat_args args;
3972   struct stat_ctx ctx;
3973   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3974   int serial;
3975
3976   if (check_state (g, "guestfs_stat") == -1) return NULL;
3977
3978   memset (&ctx, 0, sizeof ctx);
3979
3980   args.path = (char *) path;
3981   serial = guestfs__send_sync (g, GUESTFS_PROC_STAT,
3982         (xdrproc_t) xdr_guestfs_stat_args, (char *) &args);
3983   if (serial == -1)
3984     return NULL;
3985
3986   guestfs__switch_to_receiving (g);
3987   ctx.cb_sequence = 0;
3988   guestfs_set_reply_callback (g, stat_reply_cb, &ctx);
3989   (void) ml->main_loop_run (ml, g);
3990   guestfs_set_reply_callback (g, NULL, NULL);
3991   if (ctx.cb_sequence != 1001) {
3992     error (g, "%s reply failed, see earlier error messages", "guestfs_stat");
3993     return NULL;
3994   }
3995
3996   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STAT, serial) == -1)
3997     return NULL;
3998
3999   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4000     error (g, "%s", ctx.err.error_message);
4001     return NULL;
4002   }
4003
4004   /* caller will free this */
4005   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4006 }
4007
4008 struct lstat_ctx {
4009   /* This flag is set by the callbacks, so we know we've done
4010    * the callbacks as expected, and in the right sequence.
4011    * 0 = not called, 1 = send called,
4012    * 1001 = reply called.
4013    */
4014   int cb_sequence;
4015   struct guestfs_message_header hdr;
4016   struct guestfs_message_error err;
4017   struct guestfs_lstat_ret ret;
4018 };
4019
4020 static void lstat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4021 {
4022   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4023   struct lstat_ctx *ctx = (struct lstat_ctx *) data;
4024
4025   ml->main_loop_quit (ml, g);
4026
4027   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4028     error (g, "%s: failed to parse reply header", "guestfs_lstat");
4029     return;
4030   }
4031   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4032     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4033       error (g, "%s: failed to parse reply error", "guestfs_lstat");
4034       return;
4035     }
4036     goto done;
4037   }
4038   if (!xdr_guestfs_lstat_ret (xdr, &ctx->ret)) {
4039     error (g, "%s: failed to parse reply", "guestfs_lstat");
4040     return;
4041   }
4042  done:
4043   ctx->cb_sequence = 1001;
4044 }
4045
4046 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
4047                 const char *path)
4048 {
4049   struct guestfs_lstat_args args;
4050   struct lstat_ctx ctx;
4051   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4052   int serial;
4053
4054   if (check_state (g, "guestfs_lstat") == -1) return NULL;
4055
4056   memset (&ctx, 0, sizeof ctx);
4057
4058   args.path = (char *) path;
4059   serial = guestfs__send_sync (g, GUESTFS_PROC_LSTAT,
4060         (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args);
4061   if (serial == -1)
4062     return NULL;
4063
4064   guestfs__switch_to_receiving (g);
4065   ctx.cb_sequence = 0;
4066   guestfs_set_reply_callback (g, lstat_reply_cb, &ctx);
4067   (void) ml->main_loop_run (ml, g);
4068   guestfs_set_reply_callback (g, NULL, NULL);
4069   if (ctx.cb_sequence != 1001) {
4070     error (g, "%s reply failed, see earlier error messages", "guestfs_lstat");
4071     return NULL;
4072   }
4073
4074   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LSTAT, serial) == -1)
4075     return NULL;
4076
4077   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4078     error (g, "%s", ctx.err.error_message);
4079     return NULL;
4080   }
4081
4082   /* caller will free this */
4083   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4084 }
4085
4086 struct statvfs_ctx {
4087   /* This flag is set by the callbacks, so we know we've done
4088    * the callbacks as expected, and in the right sequence.
4089    * 0 = not called, 1 = send called,
4090    * 1001 = reply called.
4091    */
4092   int cb_sequence;
4093   struct guestfs_message_header hdr;
4094   struct guestfs_message_error err;
4095   struct guestfs_statvfs_ret ret;
4096 };
4097
4098 static void statvfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4099 {
4100   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4101   struct statvfs_ctx *ctx = (struct statvfs_ctx *) data;
4102
4103   ml->main_loop_quit (ml, g);
4104
4105   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4106     error (g, "%s: failed to parse reply header", "guestfs_statvfs");
4107     return;
4108   }
4109   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4110     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4111       error (g, "%s: failed to parse reply error", "guestfs_statvfs");
4112       return;
4113     }
4114     goto done;
4115   }
4116   if (!xdr_guestfs_statvfs_ret (xdr, &ctx->ret)) {
4117     error (g, "%s: failed to parse reply", "guestfs_statvfs");
4118     return;
4119   }
4120  done:
4121   ctx->cb_sequence = 1001;
4122 }
4123
4124 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
4125                 const char *path)
4126 {
4127   struct guestfs_statvfs_args args;
4128   struct statvfs_ctx ctx;
4129   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4130   int serial;
4131
4132   if (check_state (g, "guestfs_statvfs") == -1) return NULL;
4133
4134   memset (&ctx, 0, sizeof ctx);
4135
4136   args.path = (char *) path;
4137   serial = guestfs__send_sync (g, GUESTFS_PROC_STATVFS,
4138         (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args);
4139   if (serial == -1)
4140     return NULL;
4141
4142   guestfs__switch_to_receiving (g);
4143   ctx.cb_sequence = 0;
4144   guestfs_set_reply_callback (g, statvfs_reply_cb, &ctx);
4145   (void) ml->main_loop_run (ml, g);
4146   guestfs_set_reply_callback (g, NULL, NULL);
4147   if (ctx.cb_sequence != 1001) {
4148     error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs");
4149     return NULL;
4150   }
4151
4152   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STATVFS, serial) == -1)
4153     return NULL;
4154
4155   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4156     error (g, "%s", ctx.err.error_message);
4157     return NULL;
4158   }
4159
4160   /* caller will free this */
4161   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4162 }
4163
4164 struct tune2fs_l_ctx {
4165   /* This flag is set by the callbacks, so we know we've done
4166    * the callbacks as expected, and in the right sequence.
4167    * 0 = not called, 1 = send called,
4168    * 1001 = reply called.
4169    */
4170   int cb_sequence;
4171   struct guestfs_message_header hdr;
4172   struct guestfs_message_error err;
4173   struct guestfs_tune2fs_l_ret ret;
4174 };
4175
4176 static void tune2fs_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4177 {
4178   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4179   struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data;
4180
4181   ml->main_loop_quit (ml, g);
4182
4183   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4184     error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l");
4185     return;
4186   }
4187   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4188     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4189       error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l");
4190       return;
4191     }
4192     goto done;
4193   }
4194   if (!xdr_guestfs_tune2fs_l_ret (xdr, &ctx->ret)) {
4195     error (g, "%s: failed to parse reply", "guestfs_tune2fs_l");
4196     return;
4197   }
4198  done:
4199   ctx->cb_sequence = 1001;
4200 }
4201
4202 char **guestfs_tune2fs_l (guestfs_h *g,
4203                 const char *device)
4204 {
4205   struct guestfs_tune2fs_l_args args;
4206   struct tune2fs_l_ctx ctx;
4207   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4208   int serial;
4209
4210   if (check_state (g, "guestfs_tune2fs_l") == -1) return NULL;
4211
4212   memset (&ctx, 0, sizeof ctx);
4213
4214   args.device = (char *) device;
4215   serial = guestfs__send_sync (g, GUESTFS_PROC_TUNE2FS_L,
4216         (xdrproc_t) xdr_guestfs_tune2fs_l_args, (char *) &args);
4217   if (serial == -1)
4218     return NULL;
4219
4220   guestfs__switch_to_receiving (g);
4221   ctx.cb_sequence = 0;
4222   guestfs_set_reply_callback (g, tune2fs_l_reply_cb, &ctx);
4223   (void) ml->main_loop_run (ml, g);
4224   guestfs_set_reply_callback (g, NULL, NULL);
4225   if (ctx.cb_sequence != 1001) {
4226     error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l");
4227     return NULL;
4228   }
4229
4230   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1)
4231     return NULL;
4232
4233   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4234     error (g, "%s", ctx.err.error_message);
4235     return NULL;
4236   }
4237
4238   /* caller will free this, but we need to add a NULL entry */
4239   ctx.ret.superblock.superblock_val =
4240     safe_realloc (g, ctx.ret.superblock.superblock_val,
4241                   sizeof (char *) * (ctx.ret.superblock.superblock_len + 1));
4242   ctx.ret.superblock.superblock_val[ctx.ret.superblock.superblock_len] = NULL;
4243   return ctx.ret.superblock.superblock_val;
4244 }
4245
4246 struct blockdev_setro_ctx {
4247   /* This flag is set by the callbacks, so we know we've done
4248    * the callbacks as expected, and in the right sequence.
4249    * 0 = not called, 1 = send called,
4250    * 1001 = reply called.
4251    */
4252   int cb_sequence;
4253   struct guestfs_message_header hdr;
4254   struct guestfs_message_error err;
4255 };
4256
4257 static void blockdev_setro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4258 {
4259   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4260   struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data;
4261
4262   ml->main_loop_quit (ml, g);
4263
4264   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4265     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro");
4266     return;
4267   }
4268   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4269     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4270       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro");
4271       return;
4272     }
4273     goto done;
4274   }
4275  done:
4276   ctx->cb_sequence = 1001;
4277 }
4278
4279 int guestfs_blockdev_setro (guestfs_h *g,
4280                 const char *device)
4281 {
4282   struct guestfs_blockdev_setro_args args;
4283   struct blockdev_setro_ctx ctx;
4284   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4285   int serial;
4286
4287   if (check_state (g, "guestfs_blockdev_setro") == -1) return -1;
4288
4289   memset (&ctx, 0, sizeof ctx);
4290
4291   args.device = (char *) device;
4292   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRO,
4293         (xdrproc_t) xdr_guestfs_blockdev_setro_args, (char *) &args);
4294   if (serial == -1)
4295     return -1;
4296
4297   guestfs__switch_to_receiving (g);
4298   ctx.cb_sequence = 0;
4299   guestfs_set_reply_callback (g, blockdev_setro_reply_cb, &ctx);
4300   (void) ml->main_loop_run (ml, g);
4301   guestfs_set_reply_callback (g, NULL, NULL);
4302   if (ctx.cb_sequence != 1001) {
4303     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro");
4304     return -1;
4305   }
4306
4307   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1)
4308     return -1;
4309
4310   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4311     error (g, "%s", ctx.err.error_message);
4312     return -1;
4313   }
4314
4315   return 0;
4316 }
4317
4318 struct blockdev_setrw_ctx {
4319   /* This flag is set by the callbacks, so we know we've done
4320    * the callbacks as expected, and in the right sequence.
4321    * 0 = not called, 1 = send called,
4322    * 1001 = reply called.
4323    */
4324   int cb_sequence;
4325   struct guestfs_message_header hdr;
4326   struct guestfs_message_error err;
4327 };
4328
4329 static void blockdev_setrw_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4330 {
4331   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4332   struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data;
4333
4334   ml->main_loop_quit (ml, g);
4335
4336   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4337     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw");
4338     return;
4339   }
4340   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4341     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4342       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw");
4343       return;
4344     }
4345     goto done;
4346   }
4347  done:
4348   ctx->cb_sequence = 1001;
4349 }
4350
4351 int guestfs_blockdev_setrw (guestfs_h *g,
4352                 const char *device)
4353 {
4354   struct guestfs_blockdev_setrw_args args;
4355   struct blockdev_setrw_ctx ctx;
4356   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4357   int serial;
4358
4359   if (check_state (g, "guestfs_blockdev_setrw") == -1) return -1;
4360
4361   memset (&ctx, 0, sizeof ctx);
4362
4363   args.device = (char *) device;
4364   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRW,
4365         (xdrproc_t) xdr_guestfs_blockdev_setrw_args, (char *) &args);
4366   if (serial == -1)
4367     return -1;
4368
4369   guestfs__switch_to_receiving (g);
4370   ctx.cb_sequence = 0;
4371   guestfs_set_reply_callback (g, blockdev_setrw_reply_cb, &ctx);
4372   (void) ml->main_loop_run (ml, g);
4373   guestfs_set_reply_callback (g, NULL, NULL);
4374   if (ctx.cb_sequence != 1001) {
4375     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw");
4376     return -1;
4377   }
4378
4379   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1)
4380     return -1;
4381
4382   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4383     error (g, "%s", ctx.err.error_message);
4384     return -1;
4385   }
4386
4387   return 0;
4388 }
4389
4390 struct blockdev_getro_ctx {
4391   /* This flag is set by the callbacks, so we know we've done
4392    * the callbacks as expected, and in the right sequence.
4393    * 0 = not called, 1 = send called,
4394    * 1001 = reply called.
4395    */
4396   int cb_sequence;
4397   struct guestfs_message_header hdr;
4398   struct guestfs_message_error err;
4399   struct guestfs_blockdev_getro_ret ret;
4400 };
4401
4402 static void blockdev_getro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4403 {
4404   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4405   struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data;
4406
4407   ml->main_loop_quit (ml, g);
4408
4409   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4410     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro");
4411     return;
4412   }
4413   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4414     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4415       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro");
4416       return;
4417     }
4418     goto done;
4419   }
4420   if (!xdr_guestfs_blockdev_getro_ret (xdr, &ctx->ret)) {
4421     error (g, "%s: failed to parse reply", "guestfs_blockdev_getro");
4422     return;
4423   }
4424  done:
4425   ctx->cb_sequence = 1001;
4426 }
4427
4428 int guestfs_blockdev_getro (guestfs_h *g,
4429                 const char *device)
4430 {
4431   struct guestfs_blockdev_getro_args args;
4432   struct blockdev_getro_ctx ctx;
4433   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4434   int serial;
4435
4436   if (check_state (g, "guestfs_blockdev_getro") == -1) return -1;
4437
4438   memset (&ctx, 0, sizeof ctx);
4439
4440   args.device = (char *) device;
4441   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETRO,
4442         (xdrproc_t) xdr_guestfs_blockdev_getro_args, (char *) &args);
4443   if (serial == -1)
4444     return -1;
4445
4446   guestfs__switch_to_receiving (g);
4447   ctx.cb_sequence = 0;
4448   guestfs_set_reply_callback (g, blockdev_getro_reply_cb, &ctx);
4449   (void) ml->main_loop_run (ml, g);
4450   guestfs_set_reply_callback (g, NULL, NULL);
4451   if (ctx.cb_sequence != 1001) {
4452     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro");
4453     return -1;
4454   }
4455
4456   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1)
4457     return -1;
4458
4459   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4460     error (g, "%s", ctx.err.error_message);
4461     return -1;
4462   }
4463
4464   return ctx.ret.ro;
4465 }
4466
4467 struct blockdev_getss_ctx {
4468   /* This flag is set by the callbacks, so we know we've done
4469    * the callbacks as expected, and in the right sequence.
4470    * 0 = not called, 1 = send called,
4471    * 1001 = reply called.
4472    */
4473   int cb_sequence;
4474   struct guestfs_message_header hdr;
4475   struct guestfs_message_error err;
4476   struct guestfs_blockdev_getss_ret ret;
4477 };
4478
4479 static void blockdev_getss_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4480 {
4481   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4482   struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data;
4483
4484   ml->main_loop_quit (ml, g);
4485
4486   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4487     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss");
4488     return;
4489   }
4490   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4491     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4492       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss");
4493       return;
4494     }
4495     goto done;
4496   }
4497   if (!xdr_guestfs_blockdev_getss_ret (xdr, &ctx->ret)) {
4498     error (g, "%s: failed to parse reply", "guestfs_blockdev_getss");
4499     return;
4500   }
4501  done:
4502   ctx->cb_sequence = 1001;
4503 }
4504
4505 int guestfs_blockdev_getss (guestfs_h *g,
4506                 const char *device)
4507 {
4508   struct guestfs_blockdev_getss_args args;
4509   struct blockdev_getss_ctx ctx;
4510   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4511   int serial;
4512
4513   if (check_state (g, "guestfs_blockdev_getss") == -1) return -1;
4514
4515   memset (&ctx, 0, sizeof ctx);
4516
4517   args.device = (char *) device;
4518   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSS,
4519         (xdrproc_t) xdr_guestfs_blockdev_getss_args, (char *) &args);
4520   if (serial == -1)
4521     return -1;
4522
4523   guestfs__switch_to_receiving (g);
4524   ctx.cb_sequence = 0;
4525   guestfs_set_reply_callback (g, blockdev_getss_reply_cb, &ctx);
4526   (void) ml->main_loop_run (ml, g);
4527   guestfs_set_reply_callback (g, NULL, NULL);
4528   if (ctx.cb_sequence != 1001) {
4529     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss");
4530     return -1;
4531   }
4532
4533   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1)
4534     return -1;
4535
4536   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4537     error (g, "%s", ctx.err.error_message);
4538     return -1;
4539   }
4540
4541   return ctx.ret.sectorsize;
4542 }
4543
4544 struct blockdev_getbsz_ctx {
4545   /* This flag is set by the callbacks, so we know we've done
4546    * the callbacks as expected, and in the right sequence.
4547    * 0 = not called, 1 = send called,
4548    * 1001 = reply called.
4549    */
4550   int cb_sequence;
4551   struct guestfs_message_header hdr;
4552   struct guestfs_message_error err;
4553   struct guestfs_blockdev_getbsz_ret ret;
4554 };
4555
4556 static void blockdev_getbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4557 {
4558   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4559   struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data;
4560
4561   ml->main_loop_quit (ml, g);
4562
4563   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4564     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz");
4565     return;
4566   }
4567   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4568     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4569       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz");
4570       return;
4571     }
4572     goto done;
4573   }
4574   if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &ctx->ret)) {
4575     error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz");
4576     return;
4577   }
4578  done:
4579   ctx->cb_sequence = 1001;
4580 }
4581
4582 int guestfs_blockdev_getbsz (guestfs_h *g,
4583                 const char *device)
4584 {
4585   struct guestfs_blockdev_getbsz_args args;
4586   struct blockdev_getbsz_ctx ctx;
4587   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4588   int serial;
4589
4590   if (check_state (g, "guestfs_blockdev_getbsz") == -1) return -1;
4591
4592   memset (&ctx, 0, sizeof ctx);
4593
4594   args.device = (char *) device;
4595   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
4596         (xdrproc_t) xdr_guestfs_blockdev_getbsz_args, (char *) &args);
4597   if (serial == -1)
4598     return -1;
4599
4600   guestfs__switch_to_receiving (g);
4601   ctx.cb_sequence = 0;
4602   guestfs_set_reply_callback (g, blockdev_getbsz_reply_cb, &ctx);
4603   (void) ml->main_loop_run (ml, g);
4604   guestfs_set_reply_callback (g, NULL, NULL);
4605   if (ctx.cb_sequence != 1001) {
4606     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz");
4607     return -1;
4608   }
4609
4610   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1)
4611     return -1;
4612
4613   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4614     error (g, "%s", ctx.err.error_message);
4615     return -1;
4616   }
4617
4618   return ctx.ret.blocksize;
4619 }
4620
4621 struct blockdev_setbsz_ctx {
4622   /* This flag is set by the callbacks, so we know we've done
4623    * the callbacks as expected, and in the right sequence.
4624    * 0 = not called, 1 = send called,
4625    * 1001 = reply called.
4626    */
4627   int cb_sequence;
4628   struct guestfs_message_header hdr;
4629   struct guestfs_message_error err;
4630 };
4631
4632 static void blockdev_setbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4633 {
4634   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4635   struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data;
4636
4637   ml->main_loop_quit (ml, g);
4638
4639   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4640     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz");
4641     return;
4642   }
4643   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4644     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4645       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz");
4646       return;
4647     }
4648     goto done;
4649   }
4650  done:
4651   ctx->cb_sequence = 1001;
4652 }
4653
4654 int guestfs_blockdev_setbsz (guestfs_h *g,
4655                 const char *device,
4656                 int blocksize)
4657 {
4658   struct guestfs_blockdev_setbsz_args args;
4659   struct blockdev_setbsz_ctx ctx;
4660   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4661   int serial;
4662
4663   if (check_state (g, "guestfs_blockdev_setbsz") == -1) return -1;
4664
4665   memset (&ctx, 0, sizeof ctx);
4666
4667   args.device = (char *) device;
4668   args.blocksize = blocksize;
4669   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETBSZ,
4670         (xdrproc_t) xdr_guestfs_blockdev_setbsz_args, (char *) &args);
4671   if (serial == -1)
4672     return -1;
4673
4674   guestfs__switch_to_receiving (g);
4675   ctx.cb_sequence = 0;
4676   guestfs_set_reply_callback (g, blockdev_setbsz_reply_cb, &ctx);
4677   (void) ml->main_loop_run (ml, g);
4678   guestfs_set_reply_callback (g, NULL, NULL);
4679   if (ctx.cb_sequence != 1001) {
4680     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz");
4681     return -1;
4682   }
4683
4684   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1)
4685     return -1;
4686
4687   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4688     error (g, "%s", ctx.err.error_message);
4689     return -1;
4690   }
4691
4692   return 0;
4693 }
4694
4695 struct blockdev_getsz_ctx {
4696   /* This flag is set by the callbacks, so we know we've done
4697    * the callbacks as expected, and in the right sequence.
4698    * 0 = not called, 1 = send called,
4699    * 1001 = reply called.
4700    */
4701   int cb_sequence;
4702   struct guestfs_message_header hdr;
4703   struct guestfs_message_error err;
4704   struct guestfs_blockdev_getsz_ret ret;
4705 };
4706
4707 static void blockdev_getsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4708 {
4709   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4710   struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data;
4711
4712   ml->main_loop_quit (ml, g);
4713
4714   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4715     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz");
4716     return;
4717   }
4718   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4719     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4720       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz");
4721       return;
4722     }
4723     goto done;
4724   }
4725   if (!xdr_guestfs_blockdev_getsz_ret (xdr, &ctx->ret)) {
4726     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz");
4727     return;
4728   }
4729  done:
4730   ctx->cb_sequence = 1001;
4731 }
4732
4733 int64_t guestfs_blockdev_getsz (guestfs_h *g,
4734                 const char *device)
4735 {
4736   struct guestfs_blockdev_getsz_args args;
4737   struct blockdev_getsz_ctx ctx;
4738   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4739   int serial;
4740
4741   if (check_state (g, "guestfs_blockdev_getsz") == -1) return -1;
4742
4743   memset (&ctx, 0, sizeof ctx);
4744
4745   args.device = (char *) device;
4746   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
4747         (xdrproc_t) xdr_guestfs_blockdev_getsz_args, (char *) &args);
4748   if (serial == -1)
4749     return -1;
4750
4751   guestfs__switch_to_receiving (g);
4752   ctx.cb_sequence = 0;
4753   guestfs_set_reply_callback (g, blockdev_getsz_reply_cb, &ctx);
4754   (void) ml->main_loop_run (ml, g);
4755   guestfs_set_reply_callback (g, NULL, NULL);
4756   if (ctx.cb_sequence != 1001) {
4757     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz");
4758     return -1;
4759   }
4760
4761   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1)
4762     return -1;
4763
4764   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4765     error (g, "%s", ctx.err.error_message);
4766     return -1;
4767   }
4768
4769   return ctx.ret.sizeinsectors;
4770 }
4771
4772 struct blockdev_getsize64_ctx {
4773   /* This flag is set by the callbacks, so we know we've done
4774    * the callbacks as expected, and in the right sequence.
4775    * 0 = not called, 1 = send called,
4776    * 1001 = reply called.
4777    */
4778   int cb_sequence;
4779   struct guestfs_message_header hdr;
4780   struct guestfs_message_error err;
4781   struct guestfs_blockdev_getsize64_ret ret;
4782 };
4783
4784 static void blockdev_getsize64_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4785 {
4786   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4787   struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data;
4788
4789   ml->main_loop_quit (ml, g);
4790
4791   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4792     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64");
4793     return;
4794   }
4795   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4796     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4797       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64");
4798       return;
4799     }
4800     goto done;
4801   }
4802   if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &ctx->ret)) {
4803     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64");
4804     return;
4805   }
4806  done:
4807   ctx->cb_sequence = 1001;
4808 }
4809
4810 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
4811                 const char *device)
4812 {
4813   struct guestfs_blockdev_getsize64_args args;
4814   struct blockdev_getsize64_ctx ctx;
4815   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4816   int serial;
4817
4818   if (check_state (g, "guestfs_blockdev_getsize64") == -1) return -1;
4819
4820   memset (&ctx, 0, sizeof ctx);
4821
4822   args.device = (char *) device;
4823   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
4824         (xdrproc_t) xdr_guestfs_blockdev_getsize64_args, (char *) &args);
4825   if (serial == -1)
4826     return -1;
4827
4828   guestfs__switch_to_receiving (g);
4829   ctx.cb_sequence = 0;
4830   guestfs_set_reply_callback (g, blockdev_getsize64_reply_cb, &ctx);
4831   (void) ml->main_loop_run (ml, g);
4832   guestfs_set_reply_callback (g, NULL, NULL);
4833   if (ctx.cb_sequence != 1001) {
4834     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64");
4835     return -1;
4836   }
4837
4838   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1)
4839     return -1;
4840
4841   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4842     error (g, "%s", ctx.err.error_message);
4843     return -1;
4844   }
4845
4846   return ctx.ret.sizeinbytes;
4847 }
4848
4849 struct blockdev_flushbufs_ctx {
4850   /* This flag is set by the callbacks, so we know we've done
4851    * the callbacks as expected, and in the right sequence.
4852    * 0 = not called, 1 = send called,
4853    * 1001 = reply called.
4854    */
4855   int cb_sequence;
4856   struct guestfs_message_header hdr;
4857   struct guestfs_message_error err;
4858 };
4859
4860 static void blockdev_flushbufs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4861 {
4862   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4863   struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data;
4864
4865   ml->main_loop_quit (ml, g);
4866
4867   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4868     error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs");
4869     return;
4870   }
4871   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4872     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4873       error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs");
4874       return;
4875     }
4876     goto done;
4877   }
4878  done:
4879   ctx->cb_sequence = 1001;
4880 }
4881
4882 int guestfs_blockdev_flushbufs (guestfs_h *g,
4883                 const char *device)
4884 {
4885   struct guestfs_blockdev_flushbufs_args args;
4886   struct blockdev_flushbufs_ctx ctx;
4887   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4888   int serial;
4889
4890   if (check_state (g, "guestfs_blockdev_flushbufs") == -1) return -1;
4891
4892   memset (&ctx, 0, sizeof ctx);
4893
4894   args.device = (char *) device;
4895   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
4896         (xdrproc_t) xdr_guestfs_blockdev_flushbufs_args, (char *) &args);
4897   if (serial == -1)
4898     return -1;
4899
4900   guestfs__switch_to_receiving (g);
4901   ctx.cb_sequence = 0;
4902   guestfs_set_reply_callback (g, blockdev_flushbufs_reply_cb, &ctx);
4903   (void) ml->main_loop_run (ml, g);
4904   guestfs_set_reply_callback (g, NULL, NULL);
4905   if (ctx.cb_sequence != 1001) {
4906     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs");
4907     return -1;
4908   }
4909
4910   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1)
4911     return -1;
4912
4913   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4914     error (g, "%s", ctx.err.error_message);
4915     return -1;
4916   }
4917
4918   return 0;
4919 }
4920
4921 struct blockdev_rereadpt_ctx {
4922   /* This flag is set by the callbacks, so we know we've done
4923    * the callbacks as expected, and in the right sequence.
4924    * 0 = not called, 1 = send called,
4925    * 1001 = reply called.
4926    */
4927   int cb_sequence;
4928   struct guestfs_message_header hdr;
4929   struct guestfs_message_error err;
4930 };
4931
4932 static void blockdev_rereadpt_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4933 {
4934   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4935   struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data;
4936
4937   ml->main_loop_quit (ml, g);
4938
4939   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4940     error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt");
4941     return;
4942   }
4943   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4944     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4945       error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt");
4946       return;
4947     }
4948     goto done;
4949   }
4950  done:
4951   ctx->cb_sequence = 1001;
4952 }
4953
4954 int guestfs_blockdev_rereadpt (guestfs_h *g,
4955                 const char *device)
4956 {
4957   struct guestfs_blockdev_rereadpt_args args;
4958   struct blockdev_rereadpt_ctx ctx;
4959   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4960   int serial;
4961
4962   if (check_state (g, "guestfs_blockdev_rereadpt") == -1) return -1;
4963
4964   memset (&ctx, 0, sizeof ctx);
4965
4966   args.device = (char *) device;
4967   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
4968         (xdrproc_t) xdr_guestfs_blockdev_rereadpt_args, (char *) &args);
4969   if (serial == -1)
4970     return -1;
4971
4972   guestfs__switch_to_receiving (g);
4973   ctx.cb_sequence = 0;
4974   guestfs_set_reply_callback (g, blockdev_rereadpt_reply_cb, &ctx);
4975   (void) ml->main_loop_run (ml, g);
4976   guestfs_set_reply_callback (g, NULL, NULL);
4977   if (ctx.cb_sequence != 1001) {
4978     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt");
4979     return -1;
4980   }
4981
4982   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1)
4983     return -1;
4984
4985   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4986     error (g, "%s", ctx.err.error_message);
4987     return -1;
4988   }
4989
4990   return 0;
4991 }
4992
4993 struct upload_ctx {
4994   /* This flag is set by the callbacks, so we know we've done
4995    * the callbacks as expected, and in the right sequence.
4996    * 0 = not called, 1 = send called,
4997    * 1001 = reply called.
4998    */
4999   int cb_sequence;
5000   struct guestfs_message_header hdr;
5001   struct guestfs_message_error err;
5002 };
5003
5004 static void upload_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5005 {
5006   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5007   struct upload_ctx *ctx = (struct upload_ctx *) data;
5008
5009   ml->main_loop_quit (ml, g);
5010
5011   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5012     error (g, "%s: failed to parse reply header", "guestfs_upload");
5013     return;
5014   }
5015   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5016     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5017       error (g, "%s: failed to parse reply error", "guestfs_upload");
5018       return;
5019     }
5020     goto done;
5021   }
5022  done:
5023   ctx->cb_sequence = 1001;
5024 }
5025
5026 int guestfs_upload (guestfs_h *g,
5027                 const char *filename,
5028                 const char *remotefilename)
5029 {
5030   struct guestfs_upload_args args;
5031   struct upload_ctx ctx;
5032   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5033   int serial;
5034
5035   if (check_state (g, "guestfs_upload") == -1) return -1;
5036
5037   memset (&ctx, 0, sizeof ctx);
5038
5039   args.remotefilename = (char *) remotefilename;
5040   serial = guestfs__send_sync (g, GUESTFS_PROC_UPLOAD,
5041         (xdrproc_t) xdr_guestfs_upload_args, (char *) &args);
5042   if (serial == -1)
5043     return -1;
5044
5045   if (guestfs__send_file_sync (g, filename) == -1)
5046     return -1;
5047
5048   guestfs__switch_to_receiving (g);
5049   ctx.cb_sequence = 0;
5050   guestfs_set_reply_callback (g, upload_reply_cb, &ctx);
5051   (void) ml->main_loop_run (ml, g);
5052   guestfs_set_reply_callback (g, NULL, NULL);
5053   if (ctx.cb_sequence != 1001) {
5054     error (g, "%s reply failed, see earlier error messages", "guestfs_upload");
5055     return -1;
5056   }
5057
5058   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UPLOAD, serial) == -1)
5059     return -1;
5060
5061   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5062     error (g, "%s", ctx.err.error_message);
5063     return -1;
5064   }
5065
5066   return 0;
5067 }
5068
5069 struct download_ctx {
5070   /* This flag is set by the callbacks, so we know we've done
5071    * the callbacks as expected, and in the right sequence.
5072    * 0 = not called, 1 = send called,
5073    * 1001 = reply called.
5074    */
5075   int cb_sequence;
5076   struct guestfs_message_header hdr;
5077   struct guestfs_message_error err;
5078 };
5079
5080 static void download_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5081 {
5082   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5083   struct download_ctx *ctx = (struct download_ctx *) data;
5084
5085   ml->main_loop_quit (ml, g);
5086
5087   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5088     error (g, "%s: failed to parse reply header", "guestfs_download");
5089     return;
5090   }
5091   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5092     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5093       error (g, "%s: failed to parse reply error", "guestfs_download");
5094       return;
5095     }
5096     goto done;
5097   }
5098  done:
5099   ctx->cb_sequence = 1001;
5100 }
5101
5102 int guestfs_download (guestfs_h *g,
5103                 const char *remotefilename,
5104                 const char *filename)
5105 {
5106   struct guestfs_download_args args;
5107   struct download_ctx ctx;
5108   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5109   int serial;
5110
5111   if (check_state (g, "guestfs_download") == -1) return -1;
5112
5113   memset (&ctx, 0, sizeof ctx);
5114
5115   args.remotefilename = (char *) remotefilename;
5116   serial = guestfs__send_sync (g, GUESTFS_PROC_DOWNLOAD,
5117         (xdrproc_t) xdr_guestfs_download_args, (char *) &args);
5118   if (serial == -1)
5119     return -1;
5120
5121   guestfs__switch_to_receiving (g);
5122   ctx.cb_sequence = 0;
5123   guestfs_set_reply_callback (g, download_reply_cb, &ctx);
5124   (void) ml->main_loop_run (ml, g);
5125   guestfs_set_reply_callback (g, NULL, NULL);
5126   if (ctx.cb_sequence != 1001) {
5127     error (g, "%s reply failed, see earlier error messages", "guestfs_download");
5128     return -1;
5129   }
5130
5131   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1)
5132     return -1;
5133
5134   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5135     error (g, "%s", ctx.err.error_message);
5136     return -1;
5137   }
5138
5139   if (guestfs__receive_file_sync (g, filename) == -1)
5140     return -1;
5141
5142   return 0;
5143 }
5144