Begin to add the upload and download commands.
[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_send_cb (guestfs_h *g, void *data)
98 {
99   guestfs_main_loop *ml = guestfs_get_main_loop (g);
100   struct mount_ctx *ctx = (struct mount_ctx *) data;
101
102   ctx->cb_sequence = 1;
103   ml->main_loop_quit (ml, g);
104 }
105
106 static void mount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
107 {
108   guestfs_main_loop *ml = guestfs_get_main_loop (g);
109   struct mount_ctx *ctx = (struct mount_ctx *) data;
110
111   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
112     error (g, "%s: failed to parse reply header", "guestfs_mount");
113     return;
114   }
115   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
116     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
117       error (g, "%s: failed to parse reply error", "guestfs_mount");
118       return;
119     }
120     goto done;
121   }
122  done:
123   ctx->cb_sequence = 1001;
124   ml->main_loop_quit (ml, g);
125 }
126
127 int guestfs_mount (guestfs_h *g,
128                 const char *device,
129                 const char *mountpoint)
130 {
131   struct guestfs_mount_args args;
132   struct mount_ctx ctx;
133   guestfs_main_loop *ml = guestfs_get_main_loop (g);
134   int serial;
135
136   if (check_state (g, "guestfs_mount") == -1) return -1;
137
138   memset (&ctx, 0, sizeof ctx);
139
140   args.device = (char *) device;
141   args.mountpoint = (char *) mountpoint;
142   serial = guestfs__send (g, GUESTFS_PROC_MOUNT,
143         (xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
144   if (serial == -1)
145     return -1;
146
147   ctx.cb_sequence = 0;
148   guestfs_set_send_callback (g, mount_send_cb, &ctx);
149   (void) ml->main_loop_run (ml, g);
150   guestfs_set_send_callback (g, NULL, NULL);
151   if (ctx.cb_sequence != 1) {
152     error (g, "%s send failed, see earlier error messages", "guestfs_mount");
153     return -1;
154   }
155
156   guestfs__switch_to_receiving (g);
157   ctx.cb_sequence = 0;
158   guestfs_set_reply_callback (g, mount_reply_cb, &ctx);
159   (void) ml->main_loop_run (ml, g);
160   guestfs_set_reply_callback (g, NULL, NULL);
161   if (ctx.cb_sequence != 1001) {
162     error (g, "%s reply failed, see earlier error messages", "guestfs_mount");
163     return -1;
164   }
165
166   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
167     return -1;
168
169   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
170     error (g, "%s", ctx.err.error_message);
171     return -1;
172   }
173
174   return 0;
175 }
176
177 struct sync_ctx {
178   /* This flag is set by the callbacks, so we know we've done
179    * the callbacks as expected, and in the right sequence.
180    * 0 = not called, 1 = send called,
181    * 1001 = reply called.
182    */
183   int cb_sequence;
184   struct guestfs_message_header hdr;
185   struct guestfs_message_error err;
186 };
187
188 static void sync_send_cb (guestfs_h *g, void *data)
189 {
190   guestfs_main_loop *ml = guestfs_get_main_loop (g);
191   struct sync_ctx *ctx = (struct sync_ctx *) data;
192
193   ctx->cb_sequence = 1;
194   ml->main_loop_quit (ml, g);
195 }
196
197 static void sync_reply_cb (guestfs_h *g, void *data, XDR *xdr)
198 {
199   guestfs_main_loop *ml = guestfs_get_main_loop (g);
200   struct sync_ctx *ctx = (struct sync_ctx *) data;
201
202   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
203     error (g, "%s: failed to parse reply header", "guestfs_sync");
204     return;
205   }
206   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
207     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
208       error (g, "%s: failed to parse reply error", "guestfs_sync");
209       return;
210     }
211     goto done;
212   }
213  done:
214   ctx->cb_sequence = 1001;
215   ml->main_loop_quit (ml, g);
216 }
217
218 int guestfs_sync (guestfs_h *g)
219 {
220   struct sync_ctx ctx;
221   guestfs_main_loop *ml = guestfs_get_main_loop (g);
222   int serial;
223
224   if (check_state (g, "guestfs_sync") == -1) return -1;
225
226   memset (&ctx, 0, sizeof ctx);
227
228   serial = guestfs__send (g, GUESTFS_PROC_SYNC, NULL, NULL);
229   if (serial == -1)
230     return -1;
231
232   ctx.cb_sequence = 0;
233   guestfs_set_send_callback (g, sync_send_cb, &ctx);
234   (void) ml->main_loop_run (ml, g);
235   guestfs_set_send_callback (g, NULL, NULL);
236   if (ctx.cb_sequence != 1) {
237     error (g, "%s send failed, see earlier error messages", "guestfs_sync");
238     return -1;
239   }
240
241   guestfs__switch_to_receiving (g);
242   ctx.cb_sequence = 0;
243   guestfs_set_reply_callback (g, sync_reply_cb, &ctx);
244   (void) ml->main_loop_run (ml, g);
245   guestfs_set_reply_callback (g, NULL, NULL);
246   if (ctx.cb_sequence != 1001) {
247     error (g, "%s reply failed, see earlier error messages", "guestfs_sync");
248     return -1;
249   }
250
251   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SYNC, serial) == -1)
252     return -1;
253
254   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
255     error (g, "%s", ctx.err.error_message);
256     return -1;
257   }
258
259   return 0;
260 }
261
262 struct touch_ctx {
263   /* This flag is set by the callbacks, so we know we've done
264    * the callbacks as expected, and in the right sequence.
265    * 0 = not called, 1 = send called,
266    * 1001 = reply called.
267    */
268   int cb_sequence;
269   struct guestfs_message_header hdr;
270   struct guestfs_message_error err;
271 };
272
273 static void touch_send_cb (guestfs_h *g, void *data)
274 {
275   guestfs_main_loop *ml = guestfs_get_main_loop (g);
276   struct touch_ctx *ctx = (struct touch_ctx *) data;
277
278   ctx->cb_sequence = 1;
279   ml->main_loop_quit (ml, g);
280 }
281
282 static void touch_reply_cb (guestfs_h *g, void *data, XDR *xdr)
283 {
284   guestfs_main_loop *ml = guestfs_get_main_loop (g);
285   struct touch_ctx *ctx = (struct touch_ctx *) data;
286
287   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
288     error (g, "%s: failed to parse reply header", "guestfs_touch");
289     return;
290   }
291   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
292     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
293       error (g, "%s: failed to parse reply error", "guestfs_touch");
294       return;
295     }
296     goto done;
297   }
298  done:
299   ctx->cb_sequence = 1001;
300   ml->main_loop_quit (ml, g);
301 }
302
303 int guestfs_touch (guestfs_h *g,
304                 const char *path)
305 {
306   struct guestfs_touch_args args;
307   struct touch_ctx ctx;
308   guestfs_main_loop *ml = guestfs_get_main_loop (g);
309   int serial;
310
311   if (check_state (g, "guestfs_touch") == -1) return -1;
312
313   memset (&ctx, 0, sizeof ctx);
314
315   args.path = (char *) path;
316   serial = guestfs__send (g, GUESTFS_PROC_TOUCH,
317         (xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
318   if (serial == -1)
319     return -1;
320
321   ctx.cb_sequence = 0;
322   guestfs_set_send_callback (g, touch_send_cb, &ctx);
323   (void) ml->main_loop_run (ml, g);
324   guestfs_set_send_callback (g, NULL, NULL);
325   if (ctx.cb_sequence != 1) {
326     error (g, "%s send failed, see earlier error messages", "guestfs_touch");
327     return -1;
328   }
329
330   guestfs__switch_to_receiving (g);
331   ctx.cb_sequence = 0;
332   guestfs_set_reply_callback (g, touch_reply_cb, &ctx);
333   (void) ml->main_loop_run (ml, g);
334   guestfs_set_reply_callback (g, NULL, NULL);
335   if (ctx.cb_sequence != 1001) {
336     error (g, "%s reply failed, see earlier error messages", "guestfs_touch");
337     return -1;
338   }
339
340   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
341     return -1;
342
343   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
344     error (g, "%s", ctx.err.error_message);
345     return -1;
346   }
347
348   return 0;
349 }
350
351 struct cat_ctx {
352   /* This flag is set by the callbacks, so we know we've done
353    * the callbacks as expected, and in the right sequence.
354    * 0 = not called, 1 = send called,
355    * 1001 = reply called.
356    */
357   int cb_sequence;
358   struct guestfs_message_header hdr;
359   struct guestfs_message_error err;
360   struct guestfs_cat_ret ret;
361 };
362
363 static void cat_send_cb (guestfs_h *g, void *data)
364 {
365   guestfs_main_loop *ml = guestfs_get_main_loop (g);
366   struct cat_ctx *ctx = (struct cat_ctx *) data;
367
368   ctx->cb_sequence = 1;
369   ml->main_loop_quit (ml, g);
370 }
371
372 static void cat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
373 {
374   guestfs_main_loop *ml = guestfs_get_main_loop (g);
375   struct cat_ctx *ctx = (struct cat_ctx *) data;
376
377   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
378     error (g, "%s: failed to parse reply header", "guestfs_cat");
379     return;
380   }
381   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
382     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
383       error (g, "%s: failed to parse reply error", "guestfs_cat");
384       return;
385     }
386     goto done;
387   }
388   if (!xdr_guestfs_cat_ret (xdr, &ctx->ret)) {
389     error (g, "%s: failed to parse reply", "guestfs_cat");
390     return;
391   }
392  done:
393   ctx->cb_sequence = 1001;
394   ml->main_loop_quit (ml, g);
395 }
396
397 char *guestfs_cat (guestfs_h *g,
398                 const char *path)
399 {
400   struct guestfs_cat_args args;
401   struct cat_ctx ctx;
402   guestfs_main_loop *ml = guestfs_get_main_loop (g);
403   int serial;
404
405   if (check_state (g, "guestfs_cat") == -1) return NULL;
406
407   memset (&ctx, 0, sizeof ctx);
408
409   args.path = (char *) path;
410   serial = guestfs__send (g, GUESTFS_PROC_CAT,
411         (xdrproc_t) xdr_guestfs_cat_args, (char *) &args);
412   if (serial == -1)
413     return NULL;
414
415   ctx.cb_sequence = 0;
416   guestfs_set_send_callback (g, cat_send_cb, &ctx);
417   (void) ml->main_loop_run (ml, g);
418   guestfs_set_send_callback (g, NULL, NULL);
419   if (ctx.cb_sequence != 1) {
420     error (g, "%s send failed, see earlier error messages", "guestfs_cat");
421     return NULL;
422   }
423
424   guestfs__switch_to_receiving (g);
425   ctx.cb_sequence = 0;
426   guestfs_set_reply_callback (g, cat_reply_cb, &ctx);
427   (void) ml->main_loop_run (ml, g);
428   guestfs_set_reply_callback (g, NULL, NULL);
429   if (ctx.cb_sequence != 1001) {
430     error (g, "%s reply failed, see earlier error messages", "guestfs_cat");
431     return NULL;
432   }
433
434   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CAT, serial) == -1)
435     return NULL;
436
437   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
438     error (g, "%s", ctx.err.error_message);
439     return NULL;
440   }
441
442   return ctx.ret.content; /* caller will free */
443 }
444
445 struct ll_ctx {
446   /* This flag is set by the callbacks, so we know we've done
447    * the callbacks as expected, and in the right sequence.
448    * 0 = not called, 1 = send called,
449    * 1001 = reply called.
450    */
451   int cb_sequence;
452   struct guestfs_message_header hdr;
453   struct guestfs_message_error err;
454   struct guestfs_ll_ret ret;
455 };
456
457 static void ll_send_cb (guestfs_h *g, void *data)
458 {
459   guestfs_main_loop *ml = guestfs_get_main_loop (g);
460   struct ll_ctx *ctx = (struct ll_ctx *) data;
461
462   ctx->cb_sequence = 1;
463   ml->main_loop_quit (ml, g);
464 }
465
466 static void ll_reply_cb (guestfs_h *g, void *data, XDR *xdr)
467 {
468   guestfs_main_loop *ml = guestfs_get_main_loop (g);
469   struct ll_ctx *ctx = (struct ll_ctx *) data;
470
471   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
472     error (g, "%s: failed to parse reply header", "guestfs_ll");
473     return;
474   }
475   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
476     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
477       error (g, "%s: failed to parse reply error", "guestfs_ll");
478       return;
479     }
480     goto done;
481   }
482   if (!xdr_guestfs_ll_ret (xdr, &ctx->ret)) {
483     error (g, "%s: failed to parse reply", "guestfs_ll");
484     return;
485   }
486  done:
487   ctx->cb_sequence = 1001;
488   ml->main_loop_quit (ml, g);
489 }
490
491 char *guestfs_ll (guestfs_h *g,
492                 const char *directory)
493 {
494   struct guestfs_ll_args args;
495   struct ll_ctx ctx;
496   guestfs_main_loop *ml = guestfs_get_main_loop (g);
497   int serial;
498
499   if (check_state (g, "guestfs_ll") == -1) return NULL;
500
501   memset (&ctx, 0, sizeof ctx);
502
503   args.directory = (char *) directory;
504   serial = guestfs__send (g, GUESTFS_PROC_LL,
505         (xdrproc_t) xdr_guestfs_ll_args, (char *) &args);
506   if (serial == -1)
507     return NULL;
508
509   ctx.cb_sequence = 0;
510   guestfs_set_send_callback (g, ll_send_cb, &ctx);
511   (void) ml->main_loop_run (ml, g);
512   guestfs_set_send_callback (g, NULL, NULL);
513   if (ctx.cb_sequence != 1) {
514     error (g, "%s send failed, see earlier error messages", "guestfs_ll");
515     return NULL;
516   }
517
518   guestfs__switch_to_receiving (g);
519   ctx.cb_sequence = 0;
520   guestfs_set_reply_callback (g, ll_reply_cb, &ctx);
521   (void) ml->main_loop_run (ml, g);
522   guestfs_set_reply_callback (g, NULL, NULL);
523   if (ctx.cb_sequence != 1001) {
524     error (g, "%s reply failed, see earlier error messages", "guestfs_ll");
525     return NULL;
526   }
527
528   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LL, serial) == -1)
529     return NULL;
530
531   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
532     error (g, "%s", ctx.err.error_message);
533     return NULL;
534   }
535
536   return ctx.ret.listing; /* caller will free */
537 }
538
539 struct ls_ctx {
540   /* This flag is set by the callbacks, so we know we've done
541    * the callbacks as expected, and in the right sequence.
542    * 0 = not called, 1 = send called,
543    * 1001 = reply called.
544    */
545   int cb_sequence;
546   struct guestfs_message_header hdr;
547   struct guestfs_message_error err;
548   struct guestfs_ls_ret ret;
549 };
550
551 static void ls_send_cb (guestfs_h *g, void *data)
552 {
553   guestfs_main_loop *ml = guestfs_get_main_loop (g);
554   struct ls_ctx *ctx = (struct ls_ctx *) data;
555
556   ctx->cb_sequence = 1;
557   ml->main_loop_quit (ml, g);
558 }
559
560 static void ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
561 {
562   guestfs_main_loop *ml = guestfs_get_main_loop (g);
563   struct ls_ctx *ctx = (struct ls_ctx *) data;
564
565   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
566     error (g, "%s: failed to parse reply header", "guestfs_ls");
567     return;
568   }
569   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
570     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
571       error (g, "%s: failed to parse reply error", "guestfs_ls");
572       return;
573     }
574     goto done;
575   }
576   if (!xdr_guestfs_ls_ret (xdr, &ctx->ret)) {
577     error (g, "%s: failed to parse reply", "guestfs_ls");
578     return;
579   }
580  done:
581   ctx->cb_sequence = 1001;
582   ml->main_loop_quit (ml, g);
583 }
584
585 char **guestfs_ls (guestfs_h *g,
586                 const char *directory)
587 {
588   struct guestfs_ls_args args;
589   struct ls_ctx ctx;
590   guestfs_main_loop *ml = guestfs_get_main_loop (g);
591   int serial;
592
593   if (check_state (g, "guestfs_ls") == -1) return NULL;
594
595   memset (&ctx, 0, sizeof ctx);
596
597   args.directory = (char *) directory;
598   serial = guestfs__send (g, GUESTFS_PROC_LS,
599         (xdrproc_t) xdr_guestfs_ls_args, (char *) &args);
600   if (serial == -1)
601     return NULL;
602
603   ctx.cb_sequence = 0;
604   guestfs_set_send_callback (g, ls_send_cb, &ctx);
605   (void) ml->main_loop_run (ml, g);
606   guestfs_set_send_callback (g, NULL, NULL);
607   if (ctx.cb_sequence != 1) {
608     error (g, "%s send failed, see earlier error messages", "guestfs_ls");
609     return NULL;
610   }
611
612   guestfs__switch_to_receiving (g);
613   ctx.cb_sequence = 0;
614   guestfs_set_reply_callback (g, ls_reply_cb, &ctx);
615   (void) ml->main_loop_run (ml, g);
616   guestfs_set_reply_callback (g, NULL, NULL);
617   if (ctx.cb_sequence != 1001) {
618     error (g, "%s reply failed, see earlier error messages", "guestfs_ls");
619     return NULL;
620   }
621
622   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LS, serial) == -1)
623     return NULL;
624
625   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
626     error (g, "%s", ctx.err.error_message);
627     return NULL;
628   }
629
630   /* caller will free this, but we need to add a NULL entry */
631   ctx.ret.listing.listing_val =
632     safe_realloc (g, ctx.ret.listing.listing_val,
633                   sizeof (char *) * (ctx.ret.listing.listing_len + 1));
634   ctx.ret.listing.listing_val[ctx.ret.listing.listing_len] = NULL;
635   return ctx.ret.listing.listing_val;
636 }
637
638 struct list_devices_ctx {
639   /* This flag is set by the callbacks, so we know we've done
640    * the callbacks as expected, and in the right sequence.
641    * 0 = not called, 1 = send called,
642    * 1001 = reply called.
643    */
644   int cb_sequence;
645   struct guestfs_message_header hdr;
646   struct guestfs_message_error err;
647   struct guestfs_list_devices_ret ret;
648 };
649
650 static void list_devices_send_cb (guestfs_h *g, void *data)
651 {
652   guestfs_main_loop *ml = guestfs_get_main_loop (g);
653   struct list_devices_ctx *ctx = (struct list_devices_ctx *) data;
654
655   ctx->cb_sequence = 1;
656   ml->main_loop_quit (ml, g);
657 }
658
659 static void list_devices_reply_cb (guestfs_h *g, void *data, XDR *xdr)
660 {
661   guestfs_main_loop *ml = guestfs_get_main_loop (g);
662   struct list_devices_ctx *ctx = (struct list_devices_ctx *) data;
663
664   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
665     error (g, "%s: failed to parse reply header", "guestfs_list_devices");
666     return;
667   }
668   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
669     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
670       error (g, "%s: failed to parse reply error", "guestfs_list_devices");
671       return;
672     }
673     goto done;
674   }
675   if (!xdr_guestfs_list_devices_ret (xdr, &ctx->ret)) {
676     error (g, "%s: failed to parse reply", "guestfs_list_devices");
677     return;
678   }
679  done:
680   ctx->cb_sequence = 1001;
681   ml->main_loop_quit (ml, g);
682 }
683
684 char **guestfs_list_devices (guestfs_h *g)
685 {
686   struct list_devices_ctx ctx;
687   guestfs_main_loop *ml = guestfs_get_main_loop (g);
688   int serial;
689
690   if (check_state (g, "guestfs_list_devices") == -1) return NULL;
691
692   memset (&ctx, 0, sizeof ctx);
693
694   serial = guestfs__send (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
695   if (serial == -1)
696     return NULL;
697
698   ctx.cb_sequence = 0;
699   guestfs_set_send_callback (g, list_devices_send_cb, &ctx);
700   (void) ml->main_loop_run (ml, g);
701   guestfs_set_send_callback (g, NULL, NULL);
702   if (ctx.cb_sequence != 1) {
703     error (g, "%s send failed, see earlier error messages", "guestfs_list_devices");
704     return NULL;
705   }
706
707   guestfs__switch_to_receiving (g);
708   ctx.cb_sequence = 0;
709   guestfs_set_reply_callback (g, list_devices_reply_cb, &ctx);
710   (void) ml->main_loop_run (ml, g);
711   guestfs_set_reply_callback (g, NULL, NULL);
712   if (ctx.cb_sequence != 1001) {
713     error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices");
714     return NULL;
715   }
716
717   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1)
718     return NULL;
719
720   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
721     error (g, "%s", ctx.err.error_message);
722     return NULL;
723   }
724
725   /* caller will free this, but we need to add a NULL entry */
726   ctx.ret.devices.devices_val =
727     safe_realloc (g, ctx.ret.devices.devices_val,
728                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
729   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
730   return ctx.ret.devices.devices_val;
731 }
732
733 struct list_partitions_ctx {
734   /* This flag is set by the callbacks, so we know we've done
735    * the callbacks as expected, and in the right sequence.
736    * 0 = not called, 1 = send called,
737    * 1001 = reply called.
738    */
739   int cb_sequence;
740   struct guestfs_message_header hdr;
741   struct guestfs_message_error err;
742   struct guestfs_list_partitions_ret ret;
743 };
744
745 static void list_partitions_send_cb (guestfs_h *g, void *data)
746 {
747   guestfs_main_loop *ml = guestfs_get_main_loop (g);
748   struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data;
749
750   ctx->cb_sequence = 1;
751   ml->main_loop_quit (ml, g);
752 }
753
754 static void list_partitions_reply_cb (guestfs_h *g, void *data, XDR *xdr)
755 {
756   guestfs_main_loop *ml = guestfs_get_main_loop (g);
757   struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data;
758
759   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
760     error (g, "%s: failed to parse reply header", "guestfs_list_partitions");
761     return;
762   }
763   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
764     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
765       error (g, "%s: failed to parse reply error", "guestfs_list_partitions");
766       return;
767     }
768     goto done;
769   }
770   if (!xdr_guestfs_list_partitions_ret (xdr, &ctx->ret)) {
771     error (g, "%s: failed to parse reply", "guestfs_list_partitions");
772     return;
773   }
774  done:
775   ctx->cb_sequence = 1001;
776   ml->main_loop_quit (ml, g);
777 }
778
779 char **guestfs_list_partitions (guestfs_h *g)
780 {
781   struct list_partitions_ctx ctx;
782   guestfs_main_loop *ml = guestfs_get_main_loop (g);
783   int serial;
784
785   if (check_state (g, "guestfs_list_partitions") == -1) return NULL;
786
787   memset (&ctx, 0, sizeof ctx);
788
789   serial = guestfs__send (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
790   if (serial == -1)
791     return NULL;
792
793   ctx.cb_sequence = 0;
794   guestfs_set_send_callback (g, list_partitions_send_cb, &ctx);
795   (void) ml->main_loop_run (ml, g);
796   guestfs_set_send_callback (g, NULL, NULL);
797   if (ctx.cb_sequence != 1) {
798     error (g, "%s send failed, see earlier error messages", "guestfs_list_partitions");
799     return NULL;
800   }
801
802   guestfs__switch_to_receiving (g);
803   ctx.cb_sequence = 0;
804   guestfs_set_reply_callback (g, list_partitions_reply_cb, &ctx);
805   (void) ml->main_loop_run (ml, g);
806   guestfs_set_reply_callback (g, NULL, NULL);
807   if (ctx.cb_sequence != 1001) {
808     error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions");
809     return NULL;
810   }
811
812   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1)
813     return NULL;
814
815   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
816     error (g, "%s", ctx.err.error_message);
817     return NULL;
818   }
819
820   /* caller will free this, but we need to add a NULL entry */
821   ctx.ret.partitions.partitions_val =
822     safe_realloc (g, ctx.ret.partitions.partitions_val,
823                   sizeof (char *) * (ctx.ret.partitions.partitions_len + 1));
824   ctx.ret.partitions.partitions_val[ctx.ret.partitions.partitions_len] = NULL;
825   return ctx.ret.partitions.partitions_val;
826 }
827
828 struct pvs_ctx {
829   /* This flag is set by the callbacks, so we know we've done
830    * the callbacks as expected, and in the right sequence.
831    * 0 = not called, 1 = send called,
832    * 1001 = reply called.
833    */
834   int cb_sequence;
835   struct guestfs_message_header hdr;
836   struct guestfs_message_error err;
837   struct guestfs_pvs_ret ret;
838 };
839
840 static void pvs_send_cb (guestfs_h *g, void *data)
841 {
842   guestfs_main_loop *ml = guestfs_get_main_loop (g);
843   struct pvs_ctx *ctx = (struct pvs_ctx *) data;
844
845   ctx->cb_sequence = 1;
846   ml->main_loop_quit (ml, g);
847 }
848
849 static void pvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
850 {
851   guestfs_main_loop *ml = guestfs_get_main_loop (g);
852   struct pvs_ctx *ctx = (struct pvs_ctx *) data;
853
854   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
855     error (g, "%s: failed to parse reply header", "guestfs_pvs");
856     return;
857   }
858   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
859     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
860       error (g, "%s: failed to parse reply error", "guestfs_pvs");
861       return;
862     }
863     goto done;
864   }
865   if (!xdr_guestfs_pvs_ret (xdr, &ctx->ret)) {
866     error (g, "%s: failed to parse reply", "guestfs_pvs");
867     return;
868   }
869  done:
870   ctx->cb_sequence = 1001;
871   ml->main_loop_quit (ml, g);
872 }
873
874 char **guestfs_pvs (guestfs_h *g)
875 {
876   struct pvs_ctx ctx;
877   guestfs_main_loop *ml = guestfs_get_main_loop (g);
878   int serial;
879
880   if (check_state (g, "guestfs_pvs") == -1) return NULL;
881
882   memset (&ctx, 0, sizeof ctx);
883
884   serial = guestfs__send (g, GUESTFS_PROC_PVS, NULL, NULL);
885   if (serial == -1)
886     return NULL;
887
888   ctx.cb_sequence = 0;
889   guestfs_set_send_callback (g, pvs_send_cb, &ctx);
890   (void) ml->main_loop_run (ml, g);
891   guestfs_set_send_callback (g, NULL, NULL);
892   if (ctx.cb_sequence != 1) {
893     error (g, "%s send failed, see earlier error messages", "guestfs_pvs");
894     return NULL;
895   }
896
897   guestfs__switch_to_receiving (g);
898   ctx.cb_sequence = 0;
899   guestfs_set_reply_callback (g, pvs_reply_cb, &ctx);
900   (void) ml->main_loop_run (ml, g);
901   guestfs_set_reply_callback (g, NULL, NULL);
902   if (ctx.cb_sequence != 1001) {
903     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs");
904     return NULL;
905   }
906
907   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS, serial) == -1)
908     return NULL;
909
910   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
911     error (g, "%s", ctx.err.error_message);
912     return NULL;
913   }
914
915   /* caller will free this, but we need to add a NULL entry */
916   ctx.ret.physvols.physvols_val =
917     safe_realloc (g, ctx.ret.physvols.physvols_val,
918                   sizeof (char *) * (ctx.ret.physvols.physvols_len + 1));
919   ctx.ret.physvols.physvols_val[ctx.ret.physvols.physvols_len] = NULL;
920   return ctx.ret.physvols.physvols_val;
921 }
922
923 struct vgs_ctx {
924   /* This flag is set by the callbacks, so we know we've done
925    * the callbacks as expected, and in the right sequence.
926    * 0 = not called, 1 = send called,
927    * 1001 = reply called.
928    */
929   int cb_sequence;
930   struct guestfs_message_header hdr;
931   struct guestfs_message_error err;
932   struct guestfs_vgs_ret ret;
933 };
934
935 static void vgs_send_cb (guestfs_h *g, void *data)
936 {
937   guestfs_main_loop *ml = guestfs_get_main_loop (g);
938   struct vgs_ctx *ctx = (struct vgs_ctx *) data;
939
940   ctx->cb_sequence = 1;
941   ml->main_loop_quit (ml, g);
942 }
943
944 static void vgs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
945 {
946   guestfs_main_loop *ml = guestfs_get_main_loop (g);
947   struct vgs_ctx *ctx = (struct vgs_ctx *) data;
948
949   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
950     error (g, "%s: failed to parse reply header", "guestfs_vgs");
951     return;
952   }
953   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
954     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
955       error (g, "%s: failed to parse reply error", "guestfs_vgs");
956       return;
957     }
958     goto done;
959   }
960   if (!xdr_guestfs_vgs_ret (xdr, &ctx->ret)) {
961     error (g, "%s: failed to parse reply", "guestfs_vgs");
962     return;
963   }
964  done:
965   ctx->cb_sequence = 1001;
966   ml->main_loop_quit (ml, g);
967 }
968
969 char **guestfs_vgs (guestfs_h *g)
970 {
971   struct vgs_ctx ctx;
972   guestfs_main_loop *ml = guestfs_get_main_loop (g);
973   int serial;
974
975   if (check_state (g, "guestfs_vgs") == -1) return NULL;
976
977   memset (&ctx, 0, sizeof ctx);
978
979   serial = guestfs__send (g, GUESTFS_PROC_VGS, NULL, NULL);
980   if (serial == -1)
981     return NULL;
982
983   ctx.cb_sequence = 0;
984   guestfs_set_send_callback (g, vgs_send_cb, &ctx);
985   (void) ml->main_loop_run (ml, g);
986   guestfs_set_send_callback (g, NULL, NULL);
987   if (ctx.cb_sequence != 1) {
988     error (g, "%s send failed, see earlier error messages", "guestfs_vgs");
989     return NULL;
990   }
991
992   guestfs__switch_to_receiving (g);
993   ctx.cb_sequence = 0;
994   guestfs_set_reply_callback (g, vgs_reply_cb, &ctx);
995   (void) ml->main_loop_run (ml, g);
996   guestfs_set_reply_callback (g, NULL, NULL);
997   if (ctx.cb_sequence != 1001) {
998     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs");
999     return NULL;
1000   }
1001
1002   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS, serial) == -1)
1003     return NULL;
1004
1005   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1006     error (g, "%s", ctx.err.error_message);
1007     return NULL;
1008   }
1009
1010   /* caller will free this, but we need to add a NULL entry */
1011   ctx.ret.volgroups.volgroups_val =
1012     safe_realloc (g, ctx.ret.volgroups.volgroups_val,
1013                   sizeof (char *) * (ctx.ret.volgroups.volgroups_len + 1));
1014   ctx.ret.volgroups.volgroups_val[ctx.ret.volgroups.volgroups_len] = NULL;
1015   return ctx.ret.volgroups.volgroups_val;
1016 }
1017
1018 struct lvs_ctx {
1019   /* This flag is set by the callbacks, so we know we've done
1020    * the callbacks as expected, and in the right sequence.
1021    * 0 = not called, 1 = send called,
1022    * 1001 = reply called.
1023    */
1024   int cb_sequence;
1025   struct guestfs_message_header hdr;
1026   struct guestfs_message_error err;
1027   struct guestfs_lvs_ret ret;
1028 };
1029
1030 static void lvs_send_cb (guestfs_h *g, void *data)
1031 {
1032   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1033   struct lvs_ctx *ctx = (struct lvs_ctx *) data;
1034
1035   ctx->cb_sequence = 1;
1036   ml->main_loop_quit (ml, g);
1037 }
1038
1039 static void lvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1040 {
1041   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1042   struct lvs_ctx *ctx = (struct lvs_ctx *) data;
1043
1044   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1045     error (g, "%s: failed to parse reply header", "guestfs_lvs");
1046     return;
1047   }
1048   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1049     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1050       error (g, "%s: failed to parse reply error", "guestfs_lvs");
1051       return;
1052     }
1053     goto done;
1054   }
1055   if (!xdr_guestfs_lvs_ret (xdr, &ctx->ret)) {
1056     error (g, "%s: failed to parse reply", "guestfs_lvs");
1057     return;
1058   }
1059  done:
1060   ctx->cb_sequence = 1001;
1061   ml->main_loop_quit (ml, g);
1062 }
1063
1064 char **guestfs_lvs (guestfs_h *g)
1065 {
1066   struct lvs_ctx ctx;
1067   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1068   int serial;
1069
1070   if (check_state (g, "guestfs_lvs") == -1) return NULL;
1071
1072   memset (&ctx, 0, sizeof ctx);
1073
1074   serial = guestfs__send (g, GUESTFS_PROC_LVS, NULL, NULL);
1075   if (serial == -1)
1076     return NULL;
1077
1078   ctx.cb_sequence = 0;
1079   guestfs_set_send_callback (g, lvs_send_cb, &ctx);
1080   (void) ml->main_loop_run (ml, g);
1081   guestfs_set_send_callback (g, NULL, NULL);
1082   if (ctx.cb_sequence != 1) {
1083     error (g, "%s send failed, see earlier error messages", "guestfs_lvs");
1084     return NULL;
1085   }
1086
1087   guestfs__switch_to_receiving (g);
1088   ctx.cb_sequence = 0;
1089   guestfs_set_reply_callback (g, lvs_reply_cb, &ctx);
1090   (void) ml->main_loop_run (ml, g);
1091   guestfs_set_reply_callback (g, NULL, NULL);
1092   if (ctx.cb_sequence != 1001) {
1093     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs");
1094     return NULL;
1095   }
1096
1097   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS, serial) == -1)
1098     return NULL;
1099
1100   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1101     error (g, "%s", ctx.err.error_message);
1102     return NULL;
1103   }
1104
1105   /* caller will free this, but we need to add a NULL entry */
1106   ctx.ret.logvols.logvols_val =
1107     safe_realloc (g, ctx.ret.logvols.logvols_val,
1108                   sizeof (char *) * (ctx.ret.logvols.logvols_len + 1));
1109   ctx.ret.logvols.logvols_val[ctx.ret.logvols.logvols_len] = NULL;
1110   return ctx.ret.logvols.logvols_val;
1111 }
1112
1113 struct pvs_full_ctx {
1114   /* This flag is set by the callbacks, so we know we've done
1115    * the callbacks as expected, and in the right sequence.
1116    * 0 = not called, 1 = send called,
1117    * 1001 = reply called.
1118    */
1119   int cb_sequence;
1120   struct guestfs_message_header hdr;
1121   struct guestfs_message_error err;
1122   struct guestfs_pvs_full_ret ret;
1123 };
1124
1125 static void pvs_full_send_cb (guestfs_h *g, void *data)
1126 {
1127   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1128   struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data;
1129
1130   ctx->cb_sequence = 1;
1131   ml->main_loop_quit (ml, g);
1132 }
1133
1134 static void pvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1135 {
1136   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1137   struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data;
1138
1139   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1140     error (g, "%s: failed to parse reply header", "guestfs_pvs_full");
1141     return;
1142   }
1143   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1144     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1145       error (g, "%s: failed to parse reply error", "guestfs_pvs_full");
1146       return;
1147     }
1148     goto done;
1149   }
1150   if (!xdr_guestfs_pvs_full_ret (xdr, &ctx->ret)) {
1151     error (g, "%s: failed to parse reply", "guestfs_pvs_full");
1152     return;
1153   }
1154  done:
1155   ctx->cb_sequence = 1001;
1156   ml->main_loop_quit (ml, g);
1157 }
1158
1159 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
1160 {
1161   struct pvs_full_ctx ctx;
1162   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1163   int serial;
1164
1165   if (check_state (g, "guestfs_pvs_full") == -1) return NULL;
1166
1167   memset (&ctx, 0, sizeof ctx);
1168
1169   serial = guestfs__send (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
1170   if (serial == -1)
1171     return NULL;
1172
1173   ctx.cb_sequence = 0;
1174   guestfs_set_send_callback (g, pvs_full_send_cb, &ctx);
1175   (void) ml->main_loop_run (ml, g);
1176   guestfs_set_send_callback (g, NULL, NULL);
1177   if (ctx.cb_sequence != 1) {
1178     error (g, "%s send failed, see earlier error messages", "guestfs_pvs_full");
1179     return NULL;
1180   }
1181
1182   guestfs__switch_to_receiving (g);
1183   ctx.cb_sequence = 0;
1184   guestfs_set_reply_callback (g, pvs_full_reply_cb, &ctx);
1185   (void) ml->main_loop_run (ml, g);
1186   guestfs_set_reply_callback (g, NULL, NULL);
1187   if (ctx.cb_sequence != 1001) {
1188     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full");
1189     return NULL;
1190   }
1191
1192   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1)
1193     return NULL;
1194
1195   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1196     error (g, "%s", ctx.err.error_message);
1197     return NULL;
1198   }
1199
1200   /* caller will free this */
1201   return safe_memdup (g, &ctx.ret.physvols, sizeof (ctx.ret.physvols));
1202 }
1203
1204 struct vgs_full_ctx {
1205   /* This flag is set by the callbacks, so we know we've done
1206    * the callbacks as expected, and in the right sequence.
1207    * 0 = not called, 1 = send called,
1208    * 1001 = reply called.
1209    */
1210   int cb_sequence;
1211   struct guestfs_message_header hdr;
1212   struct guestfs_message_error err;
1213   struct guestfs_vgs_full_ret ret;
1214 };
1215
1216 static void vgs_full_send_cb (guestfs_h *g, void *data)
1217 {
1218   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1219   struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data;
1220
1221   ctx->cb_sequence = 1;
1222   ml->main_loop_quit (ml, g);
1223 }
1224
1225 static void vgs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1226 {
1227   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1228   struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data;
1229
1230   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1231     error (g, "%s: failed to parse reply header", "guestfs_vgs_full");
1232     return;
1233   }
1234   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1235     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1236       error (g, "%s: failed to parse reply error", "guestfs_vgs_full");
1237       return;
1238     }
1239     goto done;
1240   }
1241   if (!xdr_guestfs_vgs_full_ret (xdr, &ctx->ret)) {
1242     error (g, "%s: failed to parse reply", "guestfs_vgs_full");
1243     return;
1244   }
1245  done:
1246   ctx->cb_sequence = 1001;
1247   ml->main_loop_quit (ml, g);
1248 }
1249
1250 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
1251 {
1252   struct vgs_full_ctx ctx;
1253   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1254   int serial;
1255
1256   if (check_state (g, "guestfs_vgs_full") == -1) return NULL;
1257
1258   memset (&ctx, 0, sizeof ctx);
1259
1260   serial = guestfs__send (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
1261   if (serial == -1)
1262     return NULL;
1263
1264   ctx.cb_sequence = 0;
1265   guestfs_set_send_callback (g, vgs_full_send_cb, &ctx);
1266   (void) ml->main_loop_run (ml, g);
1267   guestfs_set_send_callback (g, NULL, NULL);
1268   if (ctx.cb_sequence != 1) {
1269     error (g, "%s send failed, see earlier error messages", "guestfs_vgs_full");
1270     return NULL;
1271   }
1272
1273   guestfs__switch_to_receiving (g);
1274   ctx.cb_sequence = 0;
1275   guestfs_set_reply_callback (g, vgs_full_reply_cb, &ctx);
1276   (void) ml->main_loop_run (ml, g);
1277   guestfs_set_reply_callback (g, NULL, NULL);
1278   if (ctx.cb_sequence != 1001) {
1279     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full");
1280     return NULL;
1281   }
1282
1283   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1)
1284     return NULL;
1285
1286   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1287     error (g, "%s", ctx.err.error_message);
1288     return NULL;
1289   }
1290
1291   /* caller will free this */
1292   return safe_memdup (g, &ctx.ret.volgroups, sizeof (ctx.ret.volgroups));
1293 }
1294
1295 struct lvs_full_ctx {
1296   /* This flag is set by the callbacks, so we know we've done
1297    * the callbacks as expected, and in the right sequence.
1298    * 0 = not called, 1 = send called,
1299    * 1001 = reply called.
1300    */
1301   int cb_sequence;
1302   struct guestfs_message_header hdr;
1303   struct guestfs_message_error err;
1304   struct guestfs_lvs_full_ret ret;
1305 };
1306
1307 static void lvs_full_send_cb (guestfs_h *g, void *data)
1308 {
1309   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1310   struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data;
1311
1312   ctx->cb_sequence = 1;
1313   ml->main_loop_quit (ml, g);
1314 }
1315
1316 static void lvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1317 {
1318   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1319   struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data;
1320
1321   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1322     error (g, "%s: failed to parse reply header", "guestfs_lvs_full");
1323     return;
1324   }
1325   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1326     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1327       error (g, "%s: failed to parse reply error", "guestfs_lvs_full");
1328       return;
1329     }
1330     goto done;
1331   }
1332   if (!xdr_guestfs_lvs_full_ret (xdr, &ctx->ret)) {
1333     error (g, "%s: failed to parse reply", "guestfs_lvs_full");
1334     return;
1335   }
1336  done:
1337   ctx->cb_sequence = 1001;
1338   ml->main_loop_quit (ml, g);
1339 }
1340
1341 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
1342 {
1343   struct lvs_full_ctx ctx;
1344   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1345   int serial;
1346
1347   if (check_state (g, "guestfs_lvs_full") == -1) return NULL;
1348
1349   memset (&ctx, 0, sizeof ctx);
1350
1351   serial = guestfs__send (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
1352   if (serial == -1)
1353     return NULL;
1354
1355   ctx.cb_sequence = 0;
1356   guestfs_set_send_callback (g, lvs_full_send_cb, &ctx);
1357   (void) ml->main_loop_run (ml, g);
1358   guestfs_set_send_callback (g, NULL, NULL);
1359   if (ctx.cb_sequence != 1) {
1360     error (g, "%s send failed, see earlier error messages", "guestfs_lvs_full");
1361     return NULL;
1362   }
1363
1364   guestfs__switch_to_receiving (g);
1365   ctx.cb_sequence = 0;
1366   guestfs_set_reply_callback (g, lvs_full_reply_cb, &ctx);
1367   (void) ml->main_loop_run (ml, g);
1368   guestfs_set_reply_callback (g, NULL, NULL);
1369   if (ctx.cb_sequence != 1001) {
1370     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full");
1371     return NULL;
1372   }
1373
1374   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1)
1375     return NULL;
1376
1377   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1378     error (g, "%s", ctx.err.error_message);
1379     return NULL;
1380   }
1381
1382   /* caller will free this */
1383   return safe_memdup (g, &ctx.ret.logvols, sizeof (ctx.ret.logvols));
1384 }
1385
1386 struct read_lines_ctx {
1387   /* This flag is set by the callbacks, so we know we've done
1388    * the callbacks as expected, and in the right sequence.
1389    * 0 = not called, 1 = send called,
1390    * 1001 = reply called.
1391    */
1392   int cb_sequence;
1393   struct guestfs_message_header hdr;
1394   struct guestfs_message_error err;
1395   struct guestfs_read_lines_ret ret;
1396 };
1397
1398 static void read_lines_send_cb (guestfs_h *g, void *data)
1399 {
1400   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1401   struct read_lines_ctx *ctx = (struct read_lines_ctx *) data;
1402
1403   ctx->cb_sequence = 1;
1404   ml->main_loop_quit (ml, g);
1405 }
1406
1407 static void read_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1408 {
1409   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1410   struct read_lines_ctx *ctx = (struct read_lines_ctx *) data;
1411
1412   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1413     error (g, "%s: failed to parse reply header", "guestfs_read_lines");
1414     return;
1415   }
1416   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1417     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1418       error (g, "%s: failed to parse reply error", "guestfs_read_lines");
1419       return;
1420     }
1421     goto done;
1422   }
1423   if (!xdr_guestfs_read_lines_ret (xdr, &ctx->ret)) {
1424     error (g, "%s: failed to parse reply", "guestfs_read_lines");
1425     return;
1426   }
1427  done:
1428   ctx->cb_sequence = 1001;
1429   ml->main_loop_quit (ml, g);
1430 }
1431
1432 char **guestfs_read_lines (guestfs_h *g,
1433                 const char *path)
1434 {
1435   struct guestfs_read_lines_args args;
1436   struct read_lines_ctx ctx;
1437   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1438   int serial;
1439
1440   if (check_state (g, "guestfs_read_lines") == -1) return NULL;
1441
1442   memset (&ctx, 0, sizeof ctx);
1443
1444   args.path = (char *) path;
1445   serial = guestfs__send (g, GUESTFS_PROC_READ_LINES,
1446         (xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args);
1447   if (serial == -1)
1448     return NULL;
1449
1450   ctx.cb_sequence = 0;
1451   guestfs_set_send_callback (g, read_lines_send_cb, &ctx);
1452   (void) ml->main_loop_run (ml, g);
1453   guestfs_set_send_callback (g, NULL, NULL);
1454   if (ctx.cb_sequence != 1) {
1455     error (g, "%s send failed, see earlier error messages", "guestfs_read_lines");
1456     return NULL;
1457   }
1458
1459   guestfs__switch_to_receiving (g);
1460   ctx.cb_sequence = 0;
1461   guestfs_set_reply_callback (g, read_lines_reply_cb, &ctx);
1462   (void) ml->main_loop_run (ml, g);
1463   guestfs_set_reply_callback (g, NULL, NULL);
1464   if (ctx.cb_sequence != 1001) {
1465     error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines");
1466     return NULL;
1467   }
1468
1469   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_READ_LINES, serial) == -1)
1470     return NULL;
1471
1472   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1473     error (g, "%s", ctx.err.error_message);
1474     return NULL;
1475   }
1476
1477   /* caller will free this, but we need to add a NULL entry */
1478   ctx.ret.lines.lines_val =
1479     safe_realloc (g, ctx.ret.lines.lines_val,
1480                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
1481   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
1482   return ctx.ret.lines.lines_val;
1483 }
1484
1485 struct aug_init_ctx {
1486   /* This flag is set by the callbacks, so we know we've done
1487    * the callbacks as expected, and in the right sequence.
1488    * 0 = not called, 1 = send called,
1489    * 1001 = reply called.
1490    */
1491   int cb_sequence;
1492   struct guestfs_message_header hdr;
1493   struct guestfs_message_error err;
1494 };
1495
1496 static void aug_init_send_cb (guestfs_h *g, void *data)
1497 {
1498   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1499   struct aug_init_ctx *ctx = (struct aug_init_ctx *) data;
1500
1501   ctx->cb_sequence = 1;
1502   ml->main_loop_quit (ml, g);
1503 }
1504
1505 static void aug_init_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1506 {
1507   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1508   struct aug_init_ctx *ctx = (struct aug_init_ctx *) data;
1509
1510   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1511     error (g, "%s: failed to parse reply header", "guestfs_aug_init");
1512     return;
1513   }
1514   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1515     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1516       error (g, "%s: failed to parse reply error", "guestfs_aug_init");
1517       return;
1518     }
1519     goto done;
1520   }
1521  done:
1522   ctx->cb_sequence = 1001;
1523   ml->main_loop_quit (ml, g);
1524 }
1525
1526 int guestfs_aug_init (guestfs_h *g,
1527                 const char *root,
1528                 int flags)
1529 {
1530   struct guestfs_aug_init_args args;
1531   struct aug_init_ctx ctx;
1532   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1533   int serial;
1534
1535   if (check_state (g, "guestfs_aug_init") == -1) return -1;
1536
1537   memset (&ctx, 0, sizeof ctx);
1538
1539   args.root = (char *) root;
1540   args.flags = flags;
1541   serial = guestfs__send (g, GUESTFS_PROC_AUG_INIT,
1542         (xdrproc_t) xdr_guestfs_aug_init_args, (char *) &args);
1543   if (serial == -1)
1544     return -1;
1545
1546   ctx.cb_sequence = 0;
1547   guestfs_set_send_callback (g, aug_init_send_cb, &ctx);
1548   (void) ml->main_loop_run (ml, g);
1549   guestfs_set_send_callback (g, NULL, NULL);
1550   if (ctx.cb_sequence != 1) {
1551     error (g, "%s send failed, see earlier error messages", "guestfs_aug_init");
1552     return -1;
1553   }
1554
1555   guestfs__switch_to_receiving (g);
1556   ctx.cb_sequence = 0;
1557   guestfs_set_reply_callback (g, aug_init_reply_cb, &ctx);
1558   (void) ml->main_loop_run (ml, g);
1559   guestfs_set_reply_callback (g, NULL, NULL);
1560   if (ctx.cb_sequence != 1001) {
1561     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init");
1562     return -1;
1563   }
1564
1565   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1)
1566     return -1;
1567
1568   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1569     error (g, "%s", ctx.err.error_message);
1570     return -1;
1571   }
1572
1573   return 0;
1574 }
1575
1576 struct aug_close_ctx {
1577   /* This flag is set by the callbacks, so we know we've done
1578    * the callbacks as expected, and in the right sequence.
1579    * 0 = not called, 1 = send called,
1580    * 1001 = reply called.
1581    */
1582   int cb_sequence;
1583   struct guestfs_message_header hdr;
1584   struct guestfs_message_error err;
1585 };
1586
1587 static void aug_close_send_cb (guestfs_h *g, void *data)
1588 {
1589   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1590   struct aug_close_ctx *ctx = (struct aug_close_ctx *) data;
1591
1592   ctx->cb_sequence = 1;
1593   ml->main_loop_quit (ml, g);
1594 }
1595
1596 static void aug_close_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1597 {
1598   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1599   struct aug_close_ctx *ctx = (struct aug_close_ctx *) data;
1600
1601   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1602     error (g, "%s: failed to parse reply header", "guestfs_aug_close");
1603     return;
1604   }
1605   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1606     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1607       error (g, "%s: failed to parse reply error", "guestfs_aug_close");
1608       return;
1609     }
1610     goto done;
1611   }
1612  done:
1613   ctx->cb_sequence = 1001;
1614   ml->main_loop_quit (ml, g);
1615 }
1616
1617 int guestfs_aug_close (guestfs_h *g)
1618 {
1619   struct aug_close_ctx ctx;
1620   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1621   int serial;
1622
1623   if (check_state (g, "guestfs_aug_close") == -1) return -1;
1624
1625   memset (&ctx, 0, sizeof ctx);
1626
1627   serial = guestfs__send (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
1628   if (serial == -1)
1629     return -1;
1630
1631   ctx.cb_sequence = 0;
1632   guestfs_set_send_callback (g, aug_close_send_cb, &ctx);
1633   (void) ml->main_loop_run (ml, g);
1634   guestfs_set_send_callback (g, NULL, NULL);
1635   if (ctx.cb_sequence != 1) {
1636     error (g, "%s send failed, see earlier error messages", "guestfs_aug_close");
1637     return -1;
1638   }
1639
1640   guestfs__switch_to_receiving (g);
1641   ctx.cb_sequence = 0;
1642   guestfs_set_reply_callback (g, aug_close_reply_cb, &ctx);
1643   (void) ml->main_loop_run (ml, g);
1644   guestfs_set_reply_callback (g, NULL, NULL);
1645   if (ctx.cb_sequence != 1001) {
1646     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close");
1647     return -1;
1648   }
1649
1650   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1)
1651     return -1;
1652
1653   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1654     error (g, "%s", ctx.err.error_message);
1655     return -1;
1656   }
1657
1658   return 0;
1659 }
1660
1661 struct aug_defvar_ctx {
1662   /* This flag is set by the callbacks, so we know we've done
1663    * the callbacks as expected, and in the right sequence.
1664    * 0 = not called, 1 = send called,
1665    * 1001 = reply called.
1666    */
1667   int cb_sequence;
1668   struct guestfs_message_header hdr;
1669   struct guestfs_message_error err;
1670   struct guestfs_aug_defvar_ret ret;
1671 };
1672
1673 static void aug_defvar_send_cb (guestfs_h *g, void *data)
1674 {
1675   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1676   struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data;
1677
1678   ctx->cb_sequence = 1;
1679   ml->main_loop_quit (ml, g);
1680 }
1681
1682 static void aug_defvar_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1683 {
1684   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1685   struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data;
1686
1687   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1688     error (g, "%s: failed to parse reply header", "guestfs_aug_defvar");
1689     return;
1690   }
1691   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1692     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1693       error (g, "%s: failed to parse reply error", "guestfs_aug_defvar");
1694       return;
1695     }
1696     goto done;
1697   }
1698   if (!xdr_guestfs_aug_defvar_ret (xdr, &ctx->ret)) {
1699     error (g, "%s: failed to parse reply", "guestfs_aug_defvar");
1700     return;
1701   }
1702  done:
1703   ctx->cb_sequence = 1001;
1704   ml->main_loop_quit (ml, g);
1705 }
1706
1707 int guestfs_aug_defvar (guestfs_h *g,
1708                 const char *name,
1709                 const char *expr)
1710 {
1711   struct guestfs_aug_defvar_args args;
1712   struct aug_defvar_ctx ctx;
1713   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1714   int serial;
1715
1716   if (check_state (g, "guestfs_aug_defvar") == -1) return -1;
1717
1718   memset (&ctx, 0, sizeof ctx);
1719
1720   args.name = (char *) name;
1721   args.expr = expr ? (char **) &expr : NULL;
1722   serial = guestfs__send (g, GUESTFS_PROC_AUG_DEFVAR,
1723         (xdrproc_t) xdr_guestfs_aug_defvar_args, (char *) &args);
1724   if (serial == -1)
1725     return -1;
1726
1727   ctx.cb_sequence = 0;
1728   guestfs_set_send_callback (g, aug_defvar_send_cb, &ctx);
1729   (void) ml->main_loop_run (ml, g);
1730   guestfs_set_send_callback (g, NULL, NULL);
1731   if (ctx.cb_sequence != 1) {
1732     error (g, "%s send failed, see earlier error messages", "guestfs_aug_defvar");
1733     return -1;
1734   }
1735
1736   guestfs__switch_to_receiving (g);
1737   ctx.cb_sequence = 0;
1738   guestfs_set_reply_callback (g, aug_defvar_reply_cb, &ctx);
1739   (void) ml->main_loop_run (ml, g);
1740   guestfs_set_reply_callback (g, NULL, NULL);
1741   if (ctx.cb_sequence != 1001) {
1742     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar");
1743     return -1;
1744   }
1745
1746   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1)
1747     return -1;
1748
1749   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1750     error (g, "%s", ctx.err.error_message);
1751     return -1;
1752   }
1753
1754   return ctx.ret.nrnodes;
1755 }
1756
1757 struct aug_defnode_ctx {
1758   /* This flag is set by the callbacks, so we know we've done
1759    * the callbacks as expected, and in the right sequence.
1760    * 0 = not called, 1 = send called,
1761    * 1001 = reply called.
1762    */
1763   int cb_sequence;
1764   struct guestfs_message_header hdr;
1765   struct guestfs_message_error err;
1766   struct guestfs_aug_defnode_ret ret;
1767 };
1768
1769 static void aug_defnode_send_cb (guestfs_h *g, void *data)
1770 {
1771   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1772   struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data;
1773
1774   ctx->cb_sequence = 1;
1775   ml->main_loop_quit (ml, g);
1776 }
1777
1778 static void aug_defnode_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1779 {
1780   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1781   struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data;
1782
1783   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1784     error (g, "%s: failed to parse reply header", "guestfs_aug_defnode");
1785     return;
1786   }
1787   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1788     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1789       error (g, "%s: failed to parse reply error", "guestfs_aug_defnode");
1790       return;
1791     }
1792     goto done;
1793   }
1794   if (!xdr_guestfs_aug_defnode_ret (xdr, &ctx->ret)) {
1795     error (g, "%s: failed to parse reply", "guestfs_aug_defnode");
1796     return;
1797   }
1798  done:
1799   ctx->cb_sequence = 1001;
1800   ml->main_loop_quit (ml, g);
1801 }
1802
1803 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
1804                 const char *name,
1805                 const char *expr,
1806                 const char *val)
1807 {
1808   struct guestfs_aug_defnode_args args;
1809   struct aug_defnode_ctx ctx;
1810   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1811   int serial;
1812
1813   if (check_state (g, "guestfs_aug_defnode") == -1) return NULL;
1814
1815   memset (&ctx, 0, sizeof ctx);
1816
1817   args.name = (char *) name;
1818   args.expr = (char *) expr;
1819   args.val = (char *) val;
1820   serial = guestfs__send (g, GUESTFS_PROC_AUG_DEFNODE,
1821         (xdrproc_t) xdr_guestfs_aug_defnode_args, (char *) &args);
1822   if (serial == -1)
1823     return NULL;
1824
1825   ctx.cb_sequence = 0;
1826   guestfs_set_send_callback (g, aug_defnode_send_cb, &ctx);
1827   (void) ml->main_loop_run (ml, g);
1828   guestfs_set_send_callback (g, NULL, NULL);
1829   if (ctx.cb_sequence != 1) {
1830     error (g, "%s send failed, see earlier error messages", "guestfs_aug_defnode");
1831     return NULL;
1832   }
1833
1834   guestfs__switch_to_receiving (g);
1835   ctx.cb_sequence = 0;
1836   guestfs_set_reply_callback (g, aug_defnode_reply_cb, &ctx);
1837   (void) ml->main_loop_run (ml, g);
1838   guestfs_set_reply_callback (g, NULL, NULL);
1839   if (ctx.cb_sequence != 1001) {
1840     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode");
1841     return NULL;
1842   }
1843
1844   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1)
1845     return NULL;
1846
1847   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1848     error (g, "%s", ctx.err.error_message);
1849     return NULL;
1850   }
1851
1852   /* caller with free this */
1853   return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));
1854 }
1855
1856 struct aug_get_ctx {
1857   /* This flag is set by the callbacks, so we know we've done
1858    * the callbacks as expected, and in the right sequence.
1859    * 0 = not called, 1 = send called,
1860    * 1001 = reply called.
1861    */
1862   int cb_sequence;
1863   struct guestfs_message_header hdr;
1864   struct guestfs_message_error err;
1865   struct guestfs_aug_get_ret ret;
1866 };
1867
1868 static void aug_get_send_cb (guestfs_h *g, void *data)
1869 {
1870   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1871   struct aug_get_ctx *ctx = (struct aug_get_ctx *) data;
1872
1873   ctx->cb_sequence = 1;
1874   ml->main_loop_quit (ml, g);
1875 }
1876
1877 static void aug_get_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1878 {
1879   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1880   struct aug_get_ctx *ctx = (struct aug_get_ctx *) data;
1881
1882   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1883     error (g, "%s: failed to parse reply header", "guestfs_aug_get");
1884     return;
1885   }
1886   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1887     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1888       error (g, "%s: failed to parse reply error", "guestfs_aug_get");
1889       return;
1890     }
1891     goto done;
1892   }
1893   if (!xdr_guestfs_aug_get_ret (xdr, &ctx->ret)) {
1894     error (g, "%s: failed to parse reply", "guestfs_aug_get");
1895     return;
1896   }
1897  done:
1898   ctx->cb_sequence = 1001;
1899   ml->main_loop_quit (ml, g);
1900 }
1901
1902 char *guestfs_aug_get (guestfs_h *g,
1903                 const char *path)
1904 {
1905   struct guestfs_aug_get_args args;
1906   struct aug_get_ctx ctx;
1907   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1908   int serial;
1909
1910   if (check_state (g, "guestfs_aug_get") == -1) return NULL;
1911
1912   memset (&ctx, 0, sizeof ctx);
1913
1914   args.path = (char *) path;
1915   serial = guestfs__send (g, GUESTFS_PROC_AUG_GET,
1916         (xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args);
1917   if (serial == -1)
1918     return NULL;
1919
1920   ctx.cb_sequence = 0;
1921   guestfs_set_send_callback (g, aug_get_send_cb, &ctx);
1922   (void) ml->main_loop_run (ml, g);
1923   guestfs_set_send_callback (g, NULL, NULL);
1924   if (ctx.cb_sequence != 1) {
1925     error (g, "%s send failed, see earlier error messages", "guestfs_aug_get");
1926     return NULL;
1927   }
1928
1929   guestfs__switch_to_receiving (g);
1930   ctx.cb_sequence = 0;
1931   guestfs_set_reply_callback (g, aug_get_reply_cb, &ctx);
1932   (void) ml->main_loop_run (ml, g);
1933   guestfs_set_reply_callback (g, NULL, NULL);
1934   if (ctx.cb_sequence != 1001) {
1935     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get");
1936     return NULL;
1937   }
1938
1939   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_GET, serial) == -1)
1940     return NULL;
1941
1942   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1943     error (g, "%s", ctx.err.error_message);
1944     return NULL;
1945   }
1946
1947   return ctx.ret.val; /* caller will free */
1948 }
1949
1950 struct aug_set_ctx {
1951   /* This flag is set by the callbacks, so we know we've done
1952    * the callbacks as expected, and in the right sequence.
1953    * 0 = not called, 1 = send called,
1954    * 1001 = reply called.
1955    */
1956   int cb_sequence;
1957   struct guestfs_message_header hdr;
1958   struct guestfs_message_error err;
1959 };
1960
1961 static void aug_set_send_cb (guestfs_h *g, void *data)
1962 {
1963   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1964   struct aug_set_ctx *ctx = (struct aug_set_ctx *) data;
1965
1966   ctx->cb_sequence = 1;
1967   ml->main_loop_quit (ml, g);
1968 }
1969
1970 static void aug_set_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1971 {
1972   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1973   struct aug_set_ctx *ctx = (struct aug_set_ctx *) data;
1974
1975   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1976     error (g, "%s: failed to parse reply header", "guestfs_aug_set");
1977     return;
1978   }
1979   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1980     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1981       error (g, "%s: failed to parse reply error", "guestfs_aug_set");
1982       return;
1983     }
1984     goto done;
1985   }
1986  done:
1987   ctx->cb_sequence = 1001;
1988   ml->main_loop_quit (ml, g);
1989 }
1990
1991 int guestfs_aug_set (guestfs_h *g,
1992                 const char *path,
1993                 const char *val)
1994 {
1995   struct guestfs_aug_set_args args;
1996   struct aug_set_ctx ctx;
1997   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1998   int serial;
1999
2000   if (check_state (g, "guestfs_aug_set") == -1) return -1;
2001
2002   memset (&ctx, 0, sizeof ctx);
2003
2004   args.path = (char *) path;
2005   args.val = (char *) val;
2006   serial = guestfs__send (g, GUESTFS_PROC_AUG_SET,
2007         (xdrproc_t) xdr_guestfs_aug_set_args, (char *) &args);
2008   if (serial == -1)
2009     return -1;
2010
2011   ctx.cb_sequence = 0;
2012   guestfs_set_send_callback (g, aug_set_send_cb, &ctx);
2013   (void) ml->main_loop_run (ml, g);
2014   guestfs_set_send_callback (g, NULL, NULL);
2015   if (ctx.cb_sequence != 1) {
2016     error (g, "%s send failed, see earlier error messages", "guestfs_aug_set");
2017     return -1;
2018   }
2019
2020   guestfs__switch_to_receiving (g);
2021   ctx.cb_sequence = 0;
2022   guestfs_set_reply_callback (g, aug_set_reply_cb, &ctx);
2023   (void) ml->main_loop_run (ml, g);
2024   guestfs_set_reply_callback (g, NULL, NULL);
2025   if (ctx.cb_sequence != 1001) {
2026     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set");
2027     return -1;
2028   }
2029
2030   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SET, serial) == -1)
2031     return -1;
2032
2033   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2034     error (g, "%s", ctx.err.error_message);
2035     return -1;
2036   }
2037
2038   return 0;
2039 }
2040
2041 struct aug_insert_ctx {
2042   /* This flag is set by the callbacks, so we know we've done
2043    * the callbacks as expected, and in the right sequence.
2044    * 0 = not called, 1 = send called,
2045    * 1001 = reply called.
2046    */
2047   int cb_sequence;
2048   struct guestfs_message_header hdr;
2049   struct guestfs_message_error err;
2050 };
2051
2052 static void aug_insert_send_cb (guestfs_h *g, void *data)
2053 {
2054   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2055   struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data;
2056
2057   ctx->cb_sequence = 1;
2058   ml->main_loop_quit (ml, g);
2059 }
2060
2061 static void aug_insert_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2062 {
2063   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2064   struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data;
2065
2066   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2067     error (g, "%s: failed to parse reply header", "guestfs_aug_insert");
2068     return;
2069   }
2070   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2071     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2072       error (g, "%s: failed to parse reply error", "guestfs_aug_insert");
2073       return;
2074     }
2075     goto done;
2076   }
2077  done:
2078   ctx->cb_sequence = 1001;
2079   ml->main_loop_quit (ml, g);
2080 }
2081
2082 int guestfs_aug_insert (guestfs_h *g,
2083                 const char *path,
2084                 const char *label,
2085                 int before)
2086 {
2087   struct guestfs_aug_insert_args args;
2088   struct aug_insert_ctx ctx;
2089   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2090   int serial;
2091
2092   if (check_state (g, "guestfs_aug_insert") == -1) return -1;
2093
2094   memset (&ctx, 0, sizeof ctx);
2095
2096   args.path = (char *) path;
2097   args.label = (char *) label;
2098   args.before = before;
2099   serial = guestfs__send (g, GUESTFS_PROC_AUG_INSERT,
2100         (xdrproc_t) xdr_guestfs_aug_insert_args, (char *) &args);
2101   if (serial == -1)
2102     return -1;
2103
2104   ctx.cb_sequence = 0;
2105   guestfs_set_send_callback (g, aug_insert_send_cb, &ctx);
2106   (void) ml->main_loop_run (ml, g);
2107   guestfs_set_send_callback (g, NULL, NULL);
2108   if (ctx.cb_sequence != 1) {
2109     error (g, "%s send failed, see earlier error messages", "guestfs_aug_insert");
2110     return -1;
2111   }
2112
2113   guestfs__switch_to_receiving (g);
2114   ctx.cb_sequence = 0;
2115   guestfs_set_reply_callback (g, aug_insert_reply_cb, &ctx);
2116   (void) ml->main_loop_run (ml, g);
2117   guestfs_set_reply_callback (g, NULL, NULL);
2118   if (ctx.cb_sequence != 1001) {
2119     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert");
2120     return -1;
2121   }
2122
2123   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1)
2124     return -1;
2125
2126   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2127     error (g, "%s", ctx.err.error_message);
2128     return -1;
2129   }
2130
2131   return 0;
2132 }
2133
2134 struct aug_rm_ctx {
2135   /* This flag is set by the callbacks, so we know we've done
2136    * the callbacks as expected, and in the right sequence.
2137    * 0 = not called, 1 = send called,
2138    * 1001 = reply called.
2139    */
2140   int cb_sequence;
2141   struct guestfs_message_header hdr;
2142   struct guestfs_message_error err;
2143   struct guestfs_aug_rm_ret ret;
2144 };
2145
2146 static void aug_rm_send_cb (guestfs_h *g, void *data)
2147 {
2148   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2149   struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data;
2150
2151   ctx->cb_sequence = 1;
2152   ml->main_loop_quit (ml, g);
2153 }
2154
2155 static void aug_rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2156 {
2157   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2158   struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data;
2159
2160   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2161     error (g, "%s: failed to parse reply header", "guestfs_aug_rm");
2162     return;
2163   }
2164   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2165     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2166       error (g, "%s: failed to parse reply error", "guestfs_aug_rm");
2167       return;
2168     }
2169     goto done;
2170   }
2171   if (!xdr_guestfs_aug_rm_ret (xdr, &ctx->ret)) {
2172     error (g, "%s: failed to parse reply", "guestfs_aug_rm");
2173     return;
2174   }
2175  done:
2176   ctx->cb_sequence = 1001;
2177   ml->main_loop_quit (ml, g);
2178 }
2179
2180 int guestfs_aug_rm (guestfs_h *g,
2181                 const char *path)
2182 {
2183   struct guestfs_aug_rm_args args;
2184   struct aug_rm_ctx ctx;
2185   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2186   int serial;
2187
2188   if (check_state (g, "guestfs_aug_rm") == -1) return -1;
2189
2190   memset (&ctx, 0, sizeof ctx);
2191
2192   args.path = (char *) path;
2193   serial = guestfs__send (g, GUESTFS_PROC_AUG_RM,
2194         (xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args);
2195   if (serial == -1)
2196     return -1;
2197
2198   ctx.cb_sequence = 0;
2199   guestfs_set_send_callback (g, aug_rm_send_cb, &ctx);
2200   (void) ml->main_loop_run (ml, g);
2201   guestfs_set_send_callback (g, NULL, NULL);
2202   if (ctx.cb_sequence != 1) {
2203     error (g, "%s send failed, see earlier error messages", "guestfs_aug_rm");
2204     return -1;
2205   }
2206
2207   guestfs__switch_to_receiving (g);
2208   ctx.cb_sequence = 0;
2209   guestfs_set_reply_callback (g, aug_rm_reply_cb, &ctx);
2210   (void) ml->main_loop_run (ml, g);
2211   guestfs_set_reply_callback (g, NULL, NULL);
2212   if (ctx.cb_sequence != 1001) {
2213     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm");
2214     return -1;
2215   }
2216
2217   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_RM, serial) == -1)
2218     return -1;
2219
2220   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2221     error (g, "%s", ctx.err.error_message);
2222     return -1;
2223   }
2224
2225   return ctx.ret.nrnodes;
2226 }
2227
2228 struct aug_mv_ctx {
2229   /* This flag is set by the callbacks, so we know we've done
2230    * the callbacks as expected, and in the right sequence.
2231    * 0 = not called, 1 = send called,
2232    * 1001 = reply called.
2233    */
2234   int cb_sequence;
2235   struct guestfs_message_header hdr;
2236   struct guestfs_message_error err;
2237 };
2238
2239 static void aug_mv_send_cb (guestfs_h *g, void *data)
2240 {
2241   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2242   struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data;
2243
2244   ctx->cb_sequence = 1;
2245   ml->main_loop_quit (ml, g);
2246 }
2247
2248 static void aug_mv_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2249 {
2250   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2251   struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data;
2252
2253   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2254     error (g, "%s: failed to parse reply header", "guestfs_aug_mv");
2255     return;
2256   }
2257   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2258     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2259       error (g, "%s: failed to parse reply error", "guestfs_aug_mv");
2260       return;
2261     }
2262     goto done;
2263   }
2264  done:
2265   ctx->cb_sequence = 1001;
2266   ml->main_loop_quit (ml, g);
2267 }
2268
2269 int guestfs_aug_mv (guestfs_h *g,
2270                 const char *src,
2271                 const char *dest)
2272 {
2273   struct guestfs_aug_mv_args args;
2274   struct aug_mv_ctx ctx;
2275   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2276   int serial;
2277
2278   if (check_state (g, "guestfs_aug_mv") == -1) return -1;
2279
2280   memset (&ctx, 0, sizeof ctx);
2281
2282   args.src = (char *) src;
2283   args.dest = (char *) dest;
2284   serial = guestfs__send (g, GUESTFS_PROC_AUG_MV,
2285         (xdrproc_t) xdr_guestfs_aug_mv_args, (char *) &args);
2286   if (serial == -1)
2287     return -1;
2288
2289   ctx.cb_sequence = 0;
2290   guestfs_set_send_callback (g, aug_mv_send_cb, &ctx);
2291   (void) ml->main_loop_run (ml, g);
2292   guestfs_set_send_callback (g, NULL, NULL);
2293   if (ctx.cb_sequence != 1) {
2294     error (g, "%s send failed, see earlier error messages", "guestfs_aug_mv");
2295     return -1;
2296   }
2297
2298   guestfs__switch_to_receiving (g);
2299   ctx.cb_sequence = 0;
2300   guestfs_set_reply_callback (g, aug_mv_reply_cb, &ctx);
2301   (void) ml->main_loop_run (ml, g);
2302   guestfs_set_reply_callback (g, NULL, NULL);
2303   if (ctx.cb_sequence != 1001) {
2304     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv");
2305     return -1;
2306   }
2307
2308   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MV, serial) == -1)
2309     return -1;
2310
2311   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2312     error (g, "%s", ctx.err.error_message);
2313     return -1;
2314   }
2315
2316   return 0;
2317 }
2318
2319 struct aug_match_ctx {
2320   /* This flag is set by the callbacks, so we know we've done
2321    * the callbacks as expected, and in the right sequence.
2322    * 0 = not called, 1 = send called,
2323    * 1001 = reply called.
2324    */
2325   int cb_sequence;
2326   struct guestfs_message_header hdr;
2327   struct guestfs_message_error err;
2328   struct guestfs_aug_match_ret ret;
2329 };
2330
2331 static void aug_match_send_cb (guestfs_h *g, void *data)
2332 {
2333   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2334   struct aug_match_ctx *ctx = (struct aug_match_ctx *) data;
2335
2336   ctx->cb_sequence = 1;
2337   ml->main_loop_quit (ml, g);
2338 }
2339
2340 static void aug_match_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2341 {
2342   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2343   struct aug_match_ctx *ctx = (struct aug_match_ctx *) data;
2344
2345   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2346     error (g, "%s: failed to parse reply header", "guestfs_aug_match");
2347     return;
2348   }
2349   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2350     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2351       error (g, "%s: failed to parse reply error", "guestfs_aug_match");
2352       return;
2353     }
2354     goto done;
2355   }
2356   if (!xdr_guestfs_aug_match_ret (xdr, &ctx->ret)) {
2357     error (g, "%s: failed to parse reply", "guestfs_aug_match");
2358     return;
2359   }
2360  done:
2361   ctx->cb_sequence = 1001;
2362   ml->main_loop_quit (ml, g);
2363 }
2364
2365 char **guestfs_aug_match (guestfs_h *g,
2366                 const char *path)
2367 {
2368   struct guestfs_aug_match_args args;
2369   struct aug_match_ctx ctx;
2370   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2371   int serial;
2372
2373   if (check_state (g, "guestfs_aug_match") == -1) return NULL;
2374
2375   memset (&ctx, 0, sizeof ctx);
2376
2377   args.path = (char *) path;
2378   serial = guestfs__send (g, GUESTFS_PROC_AUG_MATCH,
2379         (xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args);
2380   if (serial == -1)
2381     return NULL;
2382
2383   ctx.cb_sequence = 0;
2384   guestfs_set_send_callback (g, aug_match_send_cb, &ctx);
2385   (void) ml->main_loop_run (ml, g);
2386   guestfs_set_send_callback (g, NULL, NULL);
2387   if (ctx.cb_sequence != 1) {
2388     error (g, "%s send failed, see earlier error messages", "guestfs_aug_match");
2389     return NULL;
2390   }
2391
2392   guestfs__switch_to_receiving (g);
2393   ctx.cb_sequence = 0;
2394   guestfs_set_reply_callback (g, aug_match_reply_cb, &ctx);
2395   (void) ml->main_loop_run (ml, g);
2396   guestfs_set_reply_callback (g, NULL, NULL);
2397   if (ctx.cb_sequence != 1001) {
2398     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match");
2399     return NULL;
2400   }
2401
2402   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1)
2403     return NULL;
2404
2405   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2406     error (g, "%s", ctx.err.error_message);
2407     return NULL;
2408   }
2409
2410   /* caller will free this, but we need to add a NULL entry */
2411   ctx.ret.matches.matches_val =
2412     safe_realloc (g, ctx.ret.matches.matches_val,
2413                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2414   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2415   return ctx.ret.matches.matches_val;
2416 }
2417
2418 struct aug_save_ctx {
2419   /* This flag is set by the callbacks, so we know we've done
2420    * the callbacks as expected, and in the right sequence.
2421    * 0 = not called, 1 = send called,
2422    * 1001 = reply called.
2423    */
2424   int cb_sequence;
2425   struct guestfs_message_header hdr;
2426   struct guestfs_message_error err;
2427 };
2428
2429 static void aug_save_send_cb (guestfs_h *g, void *data)
2430 {
2431   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2432   struct aug_save_ctx *ctx = (struct aug_save_ctx *) data;
2433
2434   ctx->cb_sequence = 1;
2435   ml->main_loop_quit (ml, g);
2436 }
2437
2438 static void aug_save_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2439 {
2440   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2441   struct aug_save_ctx *ctx = (struct aug_save_ctx *) data;
2442
2443   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2444     error (g, "%s: failed to parse reply header", "guestfs_aug_save");
2445     return;
2446   }
2447   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2448     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2449       error (g, "%s: failed to parse reply error", "guestfs_aug_save");
2450       return;
2451     }
2452     goto done;
2453   }
2454  done:
2455   ctx->cb_sequence = 1001;
2456   ml->main_loop_quit (ml, g);
2457 }
2458
2459 int guestfs_aug_save (guestfs_h *g)
2460 {
2461   struct aug_save_ctx ctx;
2462   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2463   int serial;
2464
2465   if (check_state (g, "guestfs_aug_save") == -1) return -1;
2466
2467   memset (&ctx, 0, sizeof ctx);
2468
2469   serial = guestfs__send (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
2470   if (serial == -1)
2471     return -1;
2472
2473   ctx.cb_sequence = 0;
2474   guestfs_set_send_callback (g, aug_save_send_cb, &ctx);
2475   (void) ml->main_loop_run (ml, g);
2476   guestfs_set_send_callback (g, NULL, NULL);
2477   if (ctx.cb_sequence != 1) {
2478     error (g, "%s send failed, see earlier error messages", "guestfs_aug_save");
2479     return -1;
2480   }
2481
2482   guestfs__switch_to_receiving (g);
2483   ctx.cb_sequence = 0;
2484   guestfs_set_reply_callback (g, aug_save_reply_cb, &ctx);
2485   (void) ml->main_loop_run (ml, g);
2486   guestfs_set_reply_callback (g, NULL, NULL);
2487   if (ctx.cb_sequence != 1001) {
2488     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save");
2489     return -1;
2490   }
2491
2492   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1)
2493     return -1;
2494
2495   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2496     error (g, "%s", ctx.err.error_message);
2497     return -1;
2498   }
2499
2500   return 0;
2501 }
2502
2503 struct aug_load_ctx {
2504   /* This flag is set by the callbacks, so we know we've done
2505    * the callbacks as expected, and in the right sequence.
2506    * 0 = not called, 1 = send called,
2507    * 1001 = reply called.
2508    */
2509   int cb_sequence;
2510   struct guestfs_message_header hdr;
2511   struct guestfs_message_error err;
2512 };
2513
2514 static void aug_load_send_cb (guestfs_h *g, void *data)
2515 {
2516   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2517   struct aug_load_ctx *ctx = (struct aug_load_ctx *) data;
2518
2519   ctx->cb_sequence = 1;
2520   ml->main_loop_quit (ml, g);
2521 }
2522
2523 static void aug_load_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2524 {
2525   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2526   struct aug_load_ctx *ctx = (struct aug_load_ctx *) data;
2527
2528   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2529     error (g, "%s: failed to parse reply header", "guestfs_aug_load");
2530     return;
2531   }
2532   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2533     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2534       error (g, "%s: failed to parse reply error", "guestfs_aug_load");
2535       return;
2536     }
2537     goto done;
2538   }
2539  done:
2540   ctx->cb_sequence = 1001;
2541   ml->main_loop_quit (ml, g);
2542 }
2543
2544 int guestfs_aug_load (guestfs_h *g)
2545 {
2546   struct aug_load_ctx ctx;
2547   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2548   int serial;
2549
2550   if (check_state (g, "guestfs_aug_load") == -1) return -1;
2551
2552   memset (&ctx, 0, sizeof ctx);
2553
2554   serial = guestfs__send (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
2555   if (serial == -1)
2556     return -1;
2557
2558   ctx.cb_sequence = 0;
2559   guestfs_set_send_callback (g, aug_load_send_cb, &ctx);
2560   (void) ml->main_loop_run (ml, g);
2561   guestfs_set_send_callback (g, NULL, NULL);
2562   if (ctx.cb_sequence != 1) {
2563     error (g, "%s send failed, see earlier error messages", "guestfs_aug_load");
2564     return -1;
2565   }
2566
2567   guestfs__switch_to_receiving (g);
2568   ctx.cb_sequence = 0;
2569   guestfs_set_reply_callback (g, aug_load_reply_cb, &ctx);
2570   (void) ml->main_loop_run (ml, g);
2571   guestfs_set_reply_callback (g, NULL, NULL);
2572   if (ctx.cb_sequence != 1001) {
2573     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load");
2574     return -1;
2575   }
2576
2577   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1)
2578     return -1;
2579
2580   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2581     error (g, "%s", ctx.err.error_message);
2582     return -1;
2583   }
2584
2585   return 0;
2586 }
2587
2588 struct aug_ls_ctx {
2589   /* This flag is set by the callbacks, so we know we've done
2590    * the callbacks as expected, and in the right sequence.
2591    * 0 = not called, 1 = send called,
2592    * 1001 = reply called.
2593    */
2594   int cb_sequence;
2595   struct guestfs_message_header hdr;
2596   struct guestfs_message_error err;
2597   struct guestfs_aug_ls_ret ret;
2598 };
2599
2600 static void aug_ls_send_cb (guestfs_h *g, void *data)
2601 {
2602   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2603   struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data;
2604
2605   ctx->cb_sequence = 1;
2606   ml->main_loop_quit (ml, g);
2607 }
2608
2609 static void aug_ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2610 {
2611   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2612   struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data;
2613
2614   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2615     error (g, "%s: failed to parse reply header", "guestfs_aug_ls");
2616     return;
2617   }
2618   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2619     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2620       error (g, "%s: failed to parse reply error", "guestfs_aug_ls");
2621       return;
2622     }
2623     goto done;
2624   }
2625   if (!xdr_guestfs_aug_ls_ret (xdr, &ctx->ret)) {
2626     error (g, "%s: failed to parse reply", "guestfs_aug_ls");
2627     return;
2628   }
2629  done:
2630   ctx->cb_sequence = 1001;
2631   ml->main_loop_quit (ml, g);
2632 }
2633
2634 char **guestfs_aug_ls (guestfs_h *g,
2635                 const char *path)
2636 {
2637   struct guestfs_aug_ls_args args;
2638   struct aug_ls_ctx ctx;
2639   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2640   int serial;
2641
2642   if (check_state (g, "guestfs_aug_ls") == -1) return NULL;
2643
2644   memset (&ctx, 0, sizeof ctx);
2645
2646   args.path = (char *) path;
2647   serial = guestfs__send (g, GUESTFS_PROC_AUG_LS,
2648         (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
2649   if (serial == -1)
2650     return NULL;
2651
2652   ctx.cb_sequence = 0;
2653   guestfs_set_send_callback (g, aug_ls_send_cb, &ctx);
2654   (void) ml->main_loop_run (ml, g);
2655   guestfs_set_send_callback (g, NULL, NULL);
2656   if (ctx.cb_sequence != 1) {
2657     error (g, "%s send failed, see earlier error messages", "guestfs_aug_ls");
2658     return NULL;
2659   }
2660
2661   guestfs__switch_to_receiving (g);
2662   ctx.cb_sequence = 0;
2663   guestfs_set_reply_callback (g, aug_ls_reply_cb, &ctx);
2664   (void) ml->main_loop_run (ml, g);
2665   guestfs_set_reply_callback (g, NULL, NULL);
2666   if (ctx.cb_sequence != 1001) {
2667     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls");
2668     return NULL;
2669   }
2670
2671   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LS, serial) == -1)
2672     return NULL;
2673
2674   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2675     error (g, "%s", ctx.err.error_message);
2676     return NULL;
2677   }
2678
2679   /* caller will free this, but we need to add a NULL entry */
2680   ctx.ret.matches.matches_val =
2681     safe_realloc (g, ctx.ret.matches.matches_val,
2682                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2683   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2684   return ctx.ret.matches.matches_val;
2685 }
2686
2687 struct rm_ctx {
2688   /* This flag is set by the callbacks, so we know we've done
2689    * the callbacks as expected, and in the right sequence.
2690    * 0 = not called, 1 = send called,
2691    * 1001 = reply called.
2692    */
2693   int cb_sequence;
2694   struct guestfs_message_header hdr;
2695   struct guestfs_message_error err;
2696 };
2697
2698 static void rm_send_cb (guestfs_h *g, void *data)
2699 {
2700   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2701   struct rm_ctx *ctx = (struct rm_ctx *) data;
2702
2703   ctx->cb_sequence = 1;
2704   ml->main_loop_quit (ml, g);
2705 }
2706
2707 static void rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2708 {
2709   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2710   struct rm_ctx *ctx = (struct rm_ctx *) data;
2711
2712   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2713     error (g, "%s: failed to parse reply header", "guestfs_rm");
2714     return;
2715   }
2716   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2717     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2718       error (g, "%s: failed to parse reply error", "guestfs_rm");
2719       return;
2720     }
2721     goto done;
2722   }
2723  done:
2724   ctx->cb_sequence = 1001;
2725   ml->main_loop_quit (ml, g);
2726 }
2727
2728 int guestfs_rm (guestfs_h *g,
2729                 const char *path)
2730 {
2731   struct guestfs_rm_args args;
2732   struct rm_ctx ctx;
2733   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2734   int serial;
2735
2736   if (check_state (g, "guestfs_rm") == -1) return -1;
2737
2738   memset (&ctx, 0, sizeof ctx);
2739
2740   args.path = (char *) path;
2741   serial = guestfs__send (g, GUESTFS_PROC_RM,
2742         (xdrproc_t) xdr_guestfs_rm_args, (char *) &args);
2743   if (serial == -1)
2744     return -1;
2745
2746   ctx.cb_sequence = 0;
2747   guestfs_set_send_callback (g, rm_send_cb, &ctx);
2748   (void) ml->main_loop_run (ml, g);
2749   guestfs_set_send_callback (g, NULL, NULL);
2750   if (ctx.cb_sequence != 1) {
2751     error (g, "%s send failed, see earlier error messages", "guestfs_rm");
2752     return -1;
2753   }
2754
2755   guestfs__switch_to_receiving (g);
2756   ctx.cb_sequence = 0;
2757   guestfs_set_reply_callback (g, rm_reply_cb, &ctx);
2758   (void) ml->main_loop_run (ml, g);
2759   guestfs_set_reply_callback (g, NULL, NULL);
2760   if (ctx.cb_sequence != 1001) {
2761     error (g, "%s reply failed, see earlier error messages", "guestfs_rm");
2762     return -1;
2763   }
2764
2765   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM, serial) == -1)
2766     return -1;
2767
2768   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2769     error (g, "%s", ctx.err.error_message);
2770     return -1;
2771   }
2772
2773   return 0;
2774 }
2775
2776 struct rmdir_ctx {
2777   /* This flag is set by the callbacks, so we know we've done
2778    * the callbacks as expected, and in the right sequence.
2779    * 0 = not called, 1 = send called,
2780    * 1001 = reply called.
2781    */
2782   int cb_sequence;
2783   struct guestfs_message_header hdr;
2784   struct guestfs_message_error err;
2785 };
2786
2787 static void rmdir_send_cb (guestfs_h *g, void *data)
2788 {
2789   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2790   struct rmdir_ctx *ctx = (struct rmdir_ctx *) data;
2791
2792   ctx->cb_sequence = 1;
2793   ml->main_loop_quit (ml, g);
2794 }
2795
2796 static void rmdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2797 {
2798   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2799   struct rmdir_ctx *ctx = (struct rmdir_ctx *) data;
2800
2801   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2802     error (g, "%s: failed to parse reply header", "guestfs_rmdir");
2803     return;
2804   }
2805   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2806     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2807       error (g, "%s: failed to parse reply error", "guestfs_rmdir");
2808       return;
2809     }
2810     goto done;
2811   }
2812  done:
2813   ctx->cb_sequence = 1001;
2814   ml->main_loop_quit (ml, g);
2815 }
2816
2817 int guestfs_rmdir (guestfs_h *g,
2818                 const char *path)
2819 {
2820   struct guestfs_rmdir_args args;
2821   struct rmdir_ctx ctx;
2822   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2823   int serial;
2824
2825   if (check_state (g, "guestfs_rmdir") == -1) return -1;
2826
2827   memset (&ctx, 0, sizeof ctx);
2828
2829   args.path = (char *) path;
2830   serial = guestfs__send (g, GUESTFS_PROC_RMDIR,
2831         (xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args);
2832   if (serial == -1)
2833     return -1;
2834
2835   ctx.cb_sequence = 0;
2836   guestfs_set_send_callback (g, rmdir_send_cb, &ctx);
2837   (void) ml->main_loop_run (ml, g);
2838   guestfs_set_send_callback (g, NULL, NULL);
2839   if (ctx.cb_sequence != 1) {
2840     error (g, "%s send failed, see earlier error messages", "guestfs_rmdir");
2841     return -1;
2842   }
2843
2844   guestfs__switch_to_receiving (g);
2845   ctx.cb_sequence = 0;
2846   guestfs_set_reply_callback (g, rmdir_reply_cb, &ctx);
2847   (void) ml->main_loop_run (ml, g);
2848   guestfs_set_reply_callback (g, NULL, NULL);
2849   if (ctx.cb_sequence != 1001) {
2850     error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir");
2851     return -1;
2852   }
2853
2854   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RMDIR, serial) == -1)
2855     return -1;
2856
2857   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2858     error (g, "%s", ctx.err.error_message);
2859     return -1;
2860   }
2861
2862   return 0;
2863 }
2864
2865 struct rm_rf_ctx {
2866   /* This flag is set by the callbacks, so we know we've done
2867    * the callbacks as expected, and in the right sequence.
2868    * 0 = not called, 1 = send called,
2869    * 1001 = reply called.
2870    */
2871   int cb_sequence;
2872   struct guestfs_message_header hdr;
2873   struct guestfs_message_error err;
2874 };
2875
2876 static void rm_rf_send_cb (guestfs_h *g, void *data)
2877 {
2878   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2879   struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data;
2880
2881   ctx->cb_sequence = 1;
2882   ml->main_loop_quit (ml, g);
2883 }
2884
2885 static void rm_rf_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2886 {
2887   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2888   struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data;
2889
2890   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2891     error (g, "%s: failed to parse reply header", "guestfs_rm_rf");
2892     return;
2893   }
2894   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2895     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2896       error (g, "%s: failed to parse reply error", "guestfs_rm_rf");
2897       return;
2898     }
2899     goto done;
2900   }
2901  done:
2902   ctx->cb_sequence = 1001;
2903   ml->main_loop_quit (ml, g);
2904 }
2905
2906 int guestfs_rm_rf (guestfs_h *g,
2907                 const char *path)
2908 {
2909   struct guestfs_rm_rf_args args;
2910   struct rm_rf_ctx ctx;
2911   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2912   int serial;
2913
2914   if (check_state (g, "guestfs_rm_rf") == -1) return -1;
2915
2916   memset (&ctx, 0, sizeof ctx);
2917
2918   args.path = (char *) path;
2919   serial = guestfs__send (g, GUESTFS_PROC_RM_RF,
2920         (xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args);
2921   if (serial == -1)
2922     return -1;
2923
2924   ctx.cb_sequence = 0;
2925   guestfs_set_send_callback (g, rm_rf_send_cb, &ctx);
2926   (void) ml->main_loop_run (ml, g);
2927   guestfs_set_send_callback (g, NULL, NULL);
2928   if (ctx.cb_sequence != 1) {
2929     error (g, "%s send failed, see earlier error messages", "guestfs_rm_rf");
2930     return -1;
2931   }
2932
2933   guestfs__switch_to_receiving (g);
2934   ctx.cb_sequence = 0;
2935   guestfs_set_reply_callback (g, rm_rf_reply_cb, &ctx);
2936   (void) ml->main_loop_run (ml, g);
2937   guestfs_set_reply_callback (g, NULL, NULL);
2938   if (ctx.cb_sequence != 1001) {
2939     error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf");
2940     return -1;
2941   }
2942
2943   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM_RF, serial) == -1)
2944     return -1;
2945
2946   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2947     error (g, "%s", ctx.err.error_message);
2948     return -1;
2949   }
2950
2951   return 0;
2952 }
2953
2954 struct mkdir_ctx {
2955   /* This flag is set by the callbacks, so we know we've done
2956    * the callbacks as expected, and in the right sequence.
2957    * 0 = not called, 1 = send called,
2958    * 1001 = reply called.
2959    */
2960   int cb_sequence;
2961   struct guestfs_message_header hdr;
2962   struct guestfs_message_error err;
2963 };
2964
2965 static void mkdir_send_cb (guestfs_h *g, void *data)
2966 {
2967   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2968   struct mkdir_ctx *ctx = (struct mkdir_ctx *) data;
2969
2970   ctx->cb_sequence = 1;
2971   ml->main_loop_quit (ml, g);
2972 }
2973
2974 static void mkdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2975 {
2976   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2977   struct mkdir_ctx *ctx = (struct mkdir_ctx *) data;
2978
2979   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2980     error (g, "%s: failed to parse reply header", "guestfs_mkdir");
2981     return;
2982   }
2983   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2984     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2985       error (g, "%s: failed to parse reply error", "guestfs_mkdir");
2986       return;
2987     }
2988     goto done;
2989   }
2990  done:
2991   ctx->cb_sequence = 1001;
2992   ml->main_loop_quit (ml, g);
2993 }
2994
2995 int guestfs_mkdir (guestfs_h *g,
2996                 const char *path)
2997 {
2998   struct guestfs_mkdir_args args;
2999   struct mkdir_ctx ctx;
3000   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3001   int serial;
3002
3003   if (check_state (g, "guestfs_mkdir") == -1) return -1;
3004
3005   memset (&ctx, 0, sizeof ctx);
3006
3007   args.path = (char *) path;
3008   serial = guestfs__send (g, GUESTFS_PROC_MKDIR,
3009         (xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args);
3010   if (serial == -1)
3011     return -1;
3012
3013   ctx.cb_sequence = 0;
3014   guestfs_set_send_callback (g, mkdir_send_cb, &ctx);
3015   (void) ml->main_loop_run (ml, g);
3016   guestfs_set_send_callback (g, NULL, NULL);
3017   if (ctx.cb_sequence != 1) {
3018     error (g, "%s send failed, see earlier error messages", "guestfs_mkdir");
3019     return -1;
3020   }
3021
3022   guestfs__switch_to_receiving (g);
3023   ctx.cb_sequence = 0;
3024   guestfs_set_reply_callback (g, mkdir_reply_cb, &ctx);
3025   (void) ml->main_loop_run (ml, g);
3026   guestfs_set_reply_callback (g, NULL, NULL);
3027   if (ctx.cb_sequence != 1001) {
3028     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir");
3029     return -1;
3030   }
3031
3032   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR, serial) == -1)
3033     return -1;
3034
3035   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3036     error (g, "%s", ctx.err.error_message);
3037     return -1;
3038   }
3039
3040   return 0;
3041 }
3042
3043 struct mkdir_p_ctx {
3044   /* This flag is set by the callbacks, so we know we've done
3045    * the callbacks as expected, and in the right sequence.
3046    * 0 = not called, 1 = send called,
3047    * 1001 = reply called.
3048    */
3049   int cb_sequence;
3050   struct guestfs_message_header hdr;
3051   struct guestfs_message_error err;
3052 };
3053
3054 static void mkdir_p_send_cb (guestfs_h *g, void *data)
3055 {
3056   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3057   struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data;
3058
3059   ctx->cb_sequence = 1;
3060   ml->main_loop_quit (ml, g);
3061 }
3062
3063 static void mkdir_p_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3064 {
3065   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3066   struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data;
3067
3068   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3069     error (g, "%s: failed to parse reply header", "guestfs_mkdir_p");
3070     return;
3071   }
3072   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3073     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3074       error (g, "%s: failed to parse reply error", "guestfs_mkdir_p");
3075       return;
3076     }
3077     goto done;
3078   }
3079  done:
3080   ctx->cb_sequence = 1001;
3081   ml->main_loop_quit (ml, g);
3082 }
3083
3084 int guestfs_mkdir_p (guestfs_h *g,
3085                 const char *path)
3086 {
3087   struct guestfs_mkdir_p_args args;
3088   struct mkdir_p_ctx ctx;
3089   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3090   int serial;
3091
3092   if (check_state (g, "guestfs_mkdir_p") == -1) return -1;
3093
3094   memset (&ctx, 0, sizeof ctx);
3095
3096   args.path = (char *) path;
3097   serial = guestfs__send (g, GUESTFS_PROC_MKDIR_P,
3098         (xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args);
3099   if (serial == -1)
3100     return -1;
3101
3102   ctx.cb_sequence = 0;
3103   guestfs_set_send_callback (g, mkdir_p_send_cb, &ctx);
3104   (void) ml->main_loop_run (ml, g);
3105   guestfs_set_send_callback (g, NULL, NULL);
3106   if (ctx.cb_sequence != 1) {
3107     error (g, "%s send failed, see earlier error messages", "guestfs_mkdir_p");
3108     return -1;
3109   }
3110
3111   guestfs__switch_to_receiving (g);
3112   ctx.cb_sequence = 0;
3113   guestfs_set_reply_callback (g, mkdir_p_reply_cb, &ctx);
3114   (void) ml->main_loop_run (ml, g);
3115   guestfs_set_reply_callback (g, NULL, NULL);
3116   if (ctx.cb_sequence != 1001) {
3117     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p");
3118     return -1;
3119   }
3120
3121   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1)
3122     return -1;
3123
3124   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3125     error (g, "%s", ctx.err.error_message);
3126     return -1;
3127   }
3128
3129   return 0;
3130 }
3131
3132 struct chmod_ctx {
3133   /* This flag is set by the callbacks, so we know we've done
3134    * the callbacks as expected, and in the right sequence.
3135    * 0 = not called, 1 = send called,
3136    * 1001 = reply called.
3137    */
3138   int cb_sequence;
3139   struct guestfs_message_header hdr;
3140   struct guestfs_message_error err;
3141 };
3142
3143 static void chmod_send_cb (guestfs_h *g, void *data)
3144 {
3145   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3146   struct chmod_ctx *ctx = (struct chmod_ctx *) data;
3147
3148   ctx->cb_sequence = 1;
3149   ml->main_loop_quit (ml, g);
3150 }
3151
3152 static void chmod_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3153 {
3154   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3155   struct chmod_ctx *ctx = (struct chmod_ctx *) data;
3156
3157   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3158     error (g, "%s: failed to parse reply header", "guestfs_chmod");
3159     return;
3160   }
3161   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3162     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3163       error (g, "%s: failed to parse reply error", "guestfs_chmod");
3164       return;
3165     }
3166     goto done;
3167   }
3168  done:
3169   ctx->cb_sequence = 1001;
3170   ml->main_loop_quit (ml, g);
3171 }
3172
3173 int guestfs_chmod (guestfs_h *g,
3174                 int mode,
3175                 const char *path)
3176 {
3177   struct guestfs_chmod_args args;
3178   struct chmod_ctx ctx;
3179   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3180   int serial;
3181
3182   if (check_state (g, "guestfs_chmod") == -1) return -1;
3183
3184   memset (&ctx, 0, sizeof ctx);
3185
3186   args.mode = mode;
3187   args.path = (char *) path;
3188   serial = guestfs__send (g, GUESTFS_PROC_CHMOD,
3189         (xdrproc_t) xdr_guestfs_chmod_args, (char *) &args);
3190   if (serial == -1)
3191     return -1;
3192
3193   ctx.cb_sequence = 0;
3194   guestfs_set_send_callback (g, chmod_send_cb, &ctx);
3195   (void) ml->main_loop_run (ml, g);
3196   guestfs_set_send_callback (g, NULL, NULL);
3197   if (ctx.cb_sequence != 1) {
3198     error (g, "%s send failed, see earlier error messages", "guestfs_chmod");
3199     return -1;
3200   }
3201
3202   guestfs__switch_to_receiving (g);
3203   ctx.cb_sequence = 0;
3204   guestfs_set_reply_callback (g, chmod_reply_cb, &ctx);
3205   (void) ml->main_loop_run (ml, g);
3206   guestfs_set_reply_callback (g, NULL, NULL);
3207   if (ctx.cb_sequence != 1001) {
3208     error (g, "%s reply failed, see earlier error messages", "guestfs_chmod");
3209     return -1;
3210   }
3211
3212   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHMOD, serial) == -1)
3213     return -1;
3214
3215   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3216     error (g, "%s", ctx.err.error_message);
3217     return -1;
3218   }
3219
3220   return 0;
3221 }
3222
3223 struct chown_ctx {
3224   /* This flag is set by the callbacks, so we know we've done
3225    * the callbacks as expected, and in the right sequence.
3226    * 0 = not called, 1 = send called,
3227    * 1001 = reply called.
3228    */
3229   int cb_sequence;
3230   struct guestfs_message_header hdr;
3231   struct guestfs_message_error err;
3232 };
3233
3234 static void chown_send_cb (guestfs_h *g, void *data)
3235 {
3236   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3237   struct chown_ctx *ctx = (struct chown_ctx *) data;
3238
3239   ctx->cb_sequence = 1;
3240   ml->main_loop_quit (ml, g);
3241 }
3242
3243 static void chown_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3244 {
3245   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3246   struct chown_ctx *ctx = (struct chown_ctx *) data;
3247
3248   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3249     error (g, "%s: failed to parse reply header", "guestfs_chown");
3250     return;
3251   }
3252   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3253     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3254       error (g, "%s: failed to parse reply error", "guestfs_chown");
3255       return;
3256     }
3257     goto done;
3258   }
3259  done:
3260   ctx->cb_sequence = 1001;
3261   ml->main_loop_quit (ml, g);
3262 }
3263
3264 int guestfs_chown (guestfs_h *g,
3265                 int owner,
3266                 int group,
3267                 const char *path)
3268 {
3269   struct guestfs_chown_args args;
3270   struct chown_ctx ctx;
3271   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3272   int serial;
3273
3274   if (check_state (g, "guestfs_chown") == -1) return -1;
3275
3276   memset (&ctx, 0, sizeof ctx);
3277
3278   args.owner = owner;
3279   args.group = group;
3280   args.path = (char *) path;
3281   serial = guestfs__send (g, GUESTFS_PROC_CHOWN,
3282         (xdrproc_t) xdr_guestfs_chown_args, (char *) &args);
3283   if (serial == -1)
3284     return -1;
3285
3286   ctx.cb_sequence = 0;
3287   guestfs_set_send_callback (g, chown_send_cb, &ctx);
3288   (void) ml->main_loop_run (ml, g);
3289   guestfs_set_send_callback (g, NULL, NULL);
3290   if (ctx.cb_sequence != 1) {
3291     error (g, "%s send failed, see earlier error messages", "guestfs_chown");
3292     return -1;
3293   }
3294
3295   guestfs__switch_to_receiving (g);
3296   ctx.cb_sequence = 0;
3297   guestfs_set_reply_callback (g, chown_reply_cb, &ctx);
3298   (void) ml->main_loop_run (ml, g);
3299   guestfs_set_reply_callback (g, NULL, NULL);
3300   if (ctx.cb_sequence != 1001) {
3301     error (g, "%s reply failed, see earlier error messages", "guestfs_chown");
3302     return -1;
3303   }
3304
3305   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHOWN, serial) == -1)
3306     return -1;
3307
3308   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3309     error (g, "%s", ctx.err.error_message);
3310     return -1;
3311   }
3312
3313   return 0;
3314 }
3315
3316 struct exists_ctx {
3317   /* This flag is set by the callbacks, so we know we've done
3318    * the callbacks as expected, and in the right sequence.
3319    * 0 = not called, 1 = send called,
3320    * 1001 = reply called.
3321    */
3322   int cb_sequence;
3323   struct guestfs_message_header hdr;
3324   struct guestfs_message_error err;
3325   struct guestfs_exists_ret ret;
3326 };
3327
3328 static void exists_send_cb (guestfs_h *g, void *data)
3329 {
3330   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3331   struct exists_ctx *ctx = (struct exists_ctx *) data;
3332
3333   ctx->cb_sequence = 1;
3334   ml->main_loop_quit (ml, g);
3335 }
3336
3337 static void exists_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3338 {
3339   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3340   struct exists_ctx *ctx = (struct exists_ctx *) data;
3341
3342   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3343     error (g, "%s: failed to parse reply header", "guestfs_exists");
3344     return;
3345   }
3346   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3347     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3348       error (g, "%s: failed to parse reply error", "guestfs_exists");
3349       return;
3350     }
3351     goto done;
3352   }
3353   if (!xdr_guestfs_exists_ret (xdr, &ctx->ret)) {
3354     error (g, "%s: failed to parse reply", "guestfs_exists");
3355     return;
3356   }
3357  done:
3358   ctx->cb_sequence = 1001;
3359   ml->main_loop_quit (ml, g);
3360 }
3361
3362 int guestfs_exists (guestfs_h *g,
3363                 const char *path)
3364 {
3365   struct guestfs_exists_args args;
3366   struct exists_ctx ctx;
3367   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3368   int serial;
3369
3370   if (check_state (g, "guestfs_exists") == -1) return -1;
3371
3372   memset (&ctx, 0, sizeof ctx);
3373
3374   args.path = (char *) path;
3375   serial = guestfs__send (g, GUESTFS_PROC_EXISTS,
3376         (xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
3377   if (serial == -1)
3378     return -1;
3379
3380   ctx.cb_sequence = 0;
3381   guestfs_set_send_callback (g, exists_send_cb, &ctx);
3382   (void) ml->main_loop_run (ml, g);
3383   guestfs_set_send_callback (g, NULL, NULL);
3384   if (ctx.cb_sequence != 1) {
3385     error (g, "%s send failed, see earlier error messages", "guestfs_exists");
3386     return -1;
3387   }
3388
3389   guestfs__switch_to_receiving (g);
3390   ctx.cb_sequence = 0;
3391   guestfs_set_reply_callback (g, exists_reply_cb, &ctx);
3392   (void) ml->main_loop_run (ml, g);
3393   guestfs_set_reply_callback (g, NULL, NULL);
3394   if (ctx.cb_sequence != 1001) {
3395     error (g, "%s reply failed, see earlier error messages", "guestfs_exists");
3396     return -1;
3397   }
3398
3399   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EXISTS, serial) == -1)
3400     return -1;
3401
3402   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3403     error (g, "%s", ctx.err.error_message);
3404     return -1;
3405   }
3406
3407   return ctx.ret.existsflag;
3408 }
3409
3410 struct is_file_ctx {
3411   /* This flag is set by the callbacks, so we know we've done
3412    * the callbacks as expected, and in the right sequence.
3413    * 0 = not called, 1 = send called,
3414    * 1001 = reply called.
3415    */
3416   int cb_sequence;
3417   struct guestfs_message_header hdr;
3418   struct guestfs_message_error err;
3419   struct guestfs_is_file_ret ret;
3420 };
3421
3422 static void is_file_send_cb (guestfs_h *g, void *data)
3423 {
3424   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3425   struct is_file_ctx *ctx = (struct is_file_ctx *) data;
3426
3427   ctx->cb_sequence = 1;
3428   ml->main_loop_quit (ml, g);
3429 }
3430
3431 static void is_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3432 {
3433   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3434   struct is_file_ctx *ctx = (struct is_file_ctx *) data;
3435
3436   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3437     error (g, "%s: failed to parse reply header", "guestfs_is_file");
3438     return;
3439   }
3440   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3441     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3442       error (g, "%s: failed to parse reply error", "guestfs_is_file");
3443       return;
3444     }
3445     goto done;
3446   }
3447   if (!xdr_guestfs_is_file_ret (xdr, &ctx->ret)) {
3448     error (g, "%s: failed to parse reply", "guestfs_is_file");
3449     return;
3450   }
3451  done:
3452   ctx->cb_sequence = 1001;
3453   ml->main_loop_quit (ml, g);
3454 }
3455
3456 int guestfs_is_file (guestfs_h *g,
3457                 const char *path)
3458 {
3459   struct guestfs_is_file_args args;
3460   struct is_file_ctx ctx;
3461   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3462   int serial;
3463
3464   if (check_state (g, "guestfs_is_file") == -1) return -1;
3465
3466   memset (&ctx, 0, sizeof ctx);
3467
3468   args.path = (char *) path;
3469   serial = guestfs__send (g, GUESTFS_PROC_IS_FILE,
3470         (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
3471   if (serial == -1)
3472     return -1;
3473
3474   ctx.cb_sequence = 0;
3475   guestfs_set_send_callback (g, is_file_send_cb, &ctx);
3476   (void) ml->main_loop_run (ml, g);
3477   guestfs_set_send_callback (g, NULL, NULL);
3478   if (ctx.cb_sequence != 1) {
3479     error (g, "%s send failed, see earlier error messages", "guestfs_is_file");
3480     return -1;
3481   }
3482
3483   guestfs__switch_to_receiving (g);
3484   ctx.cb_sequence = 0;
3485   guestfs_set_reply_callback (g, is_file_reply_cb, &ctx);
3486   (void) ml->main_loop_run (ml, g);
3487   guestfs_set_reply_callback (g, NULL, NULL);
3488   if (ctx.cb_sequence != 1001) {
3489     error (g, "%s reply failed, see earlier error messages", "guestfs_is_file");
3490     return -1;
3491   }
3492
3493   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_FILE, serial) == -1)
3494     return -1;
3495
3496   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3497     error (g, "%s", ctx.err.error_message);
3498     return -1;
3499   }
3500
3501   return ctx.ret.fileflag;
3502 }
3503
3504 struct is_dir_ctx {
3505   /* This flag is set by the callbacks, so we know we've done
3506    * the callbacks as expected, and in the right sequence.
3507    * 0 = not called, 1 = send called,
3508    * 1001 = reply called.
3509    */
3510   int cb_sequence;
3511   struct guestfs_message_header hdr;
3512   struct guestfs_message_error err;
3513   struct guestfs_is_dir_ret ret;
3514 };
3515
3516 static void is_dir_send_cb (guestfs_h *g, void *data)
3517 {
3518   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3519   struct is_dir_ctx *ctx = (struct is_dir_ctx *) data;
3520
3521   ctx->cb_sequence = 1;
3522   ml->main_loop_quit (ml, g);
3523 }
3524
3525 static void is_dir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3526 {
3527   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3528   struct is_dir_ctx *ctx = (struct is_dir_ctx *) data;
3529
3530   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3531     error (g, "%s: failed to parse reply header", "guestfs_is_dir");
3532     return;
3533   }
3534   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3535     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3536       error (g, "%s: failed to parse reply error", "guestfs_is_dir");
3537       return;
3538     }
3539     goto done;
3540   }
3541   if (!xdr_guestfs_is_dir_ret (xdr, &ctx->ret)) {
3542     error (g, "%s: failed to parse reply", "guestfs_is_dir");
3543     return;
3544   }
3545  done:
3546   ctx->cb_sequence = 1001;
3547   ml->main_loop_quit (ml, g);
3548 }
3549
3550 int guestfs_is_dir (guestfs_h *g,
3551                 const char *path)
3552 {
3553   struct guestfs_is_dir_args args;
3554   struct is_dir_ctx ctx;
3555   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3556   int serial;
3557
3558   if (check_state (g, "guestfs_is_dir") == -1) return -1;
3559
3560   memset (&ctx, 0, sizeof ctx);
3561
3562   args.path = (char *) path;
3563   serial = guestfs__send (g, GUESTFS_PROC_IS_DIR,
3564         (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
3565   if (serial == -1)
3566     return -1;
3567
3568   ctx.cb_sequence = 0;
3569   guestfs_set_send_callback (g, is_dir_send_cb, &ctx);
3570   (void) ml->main_loop_run (ml, g);
3571   guestfs_set_send_callback (g, NULL, NULL);
3572   if (ctx.cb_sequence != 1) {
3573     error (g, "%s send failed, see earlier error messages", "guestfs_is_dir");
3574     return -1;
3575   }
3576
3577   guestfs__switch_to_receiving (g);
3578   ctx.cb_sequence = 0;
3579   guestfs_set_reply_callback (g, is_dir_reply_cb, &ctx);
3580   (void) ml->main_loop_run (ml, g);
3581   guestfs_set_reply_callback (g, NULL, NULL);
3582   if (ctx.cb_sequence != 1001) {
3583     error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir");
3584     return -1;
3585   }
3586
3587   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_DIR, serial) == -1)
3588     return -1;
3589
3590   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3591     error (g, "%s", ctx.err.error_message);
3592     return -1;
3593   }
3594
3595   return ctx.ret.dirflag;
3596 }
3597
3598 struct pvcreate_ctx {
3599   /* This flag is set by the callbacks, so we know we've done
3600    * the callbacks as expected, and in the right sequence.
3601    * 0 = not called, 1 = send called,
3602    * 1001 = reply called.
3603    */
3604   int cb_sequence;
3605   struct guestfs_message_header hdr;
3606   struct guestfs_message_error err;
3607 };
3608
3609 static void pvcreate_send_cb (guestfs_h *g, void *data)
3610 {
3611   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3612   struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data;
3613
3614   ctx->cb_sequence = 1;
3615   ml->main_loop_quit (ml, g);
3616 }
3617
3618 static void pvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3619 {
3620   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3621   struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data;
3622
3623   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3624     error (g, "%s: failed to parse reply header", "guestfs_pvcreate");
3625     return;
3626   }
3627   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3628     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3629       error (g, "%s: failed to parse reply error", "guestfs_pvcreate");
3630       return;
3631     }
3632     goto done;
3633   }
3634  done:
3635   ctx->cb_sequence = 1001;
3636   ml->main_loop_quit (ml, g);
3637 }
3638
3639 int guestfs_pvcreate (guestfs_h *g,
3640                 const char *device)
3641 {
3642   struct guestfs_pvcreate_args args;
3643   struct pvcreate_ctx ctx;
3644   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3645   int serial;
3646
3647   if (check_state (g, "guestfs_pvcreate") == -1) return -1;
3648
3649   memset (&ctx, 0, sizeof ctx);
3650
3651   args.device = (char *) device;
3652   serial = guestfs__send (g, GUESTFS_PROC_PVCREATE,
3653         (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
3654   if (serial == -1)
3655     return -1;
3656
3657   ctx.cb_sequence = 0;
3658   guestfs_set_send_callback (g, pvcreate_send_cb, &ctx);
3659   (void) ml->main_loop_run (ml, g);
3660   guestfs_set_send_callback (g, NULL, NULL);
3661   if (ctx.cb_sequence != 1) {
3662     error (g, "%s send failed, see earlier error messages", "guestfs_pvcreate");
3663     return -1;
3664   }
3665
3666   guestfs__switch_to_receiving (g);
3667   ctx.cb_sequence = 0;
3668   guestfs_set_reply_callback (g, pvcreate_reply_cb, &ctx);
3669   (void) ml->main_loop_run (ml, g);
3670   guestfs_set_reply_callback (g, NULL, NULL);
3671   if (ctx.cb_sequence != 1001) {
3672     error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate");
3673     return -1;
3674   }
3675
3676   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVCREATE, serial) == -1)
3677     return -1;
3678
3679   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3680     error (g, "%s", ctx.err.error_message);
3681     return -1;
3682   }
3683
3684   return 0;
3685 }
3686
3687 struct vgcreate_ctx {
3688   /* This flag is set by the callbacks, so we know we've done
3689    * the callbacks as expected, and in the right sequence.
3690    * 0 = not called, 1 = send called,
3691    * 1001 = reply called.
3692    */
3693   int cb_sequence;
3694   struct guestfs_message_header hdr;
3695   struct guestfs_message_error err;
3696 };
3697
3698 static void vgcreate_send_cb (guestfs_h *g, void *data)
3699 {
3700   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3701   struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data;
3702
3703   ctx->cb_sequence = 1;
3704   ml->main_loop_quit (ml, g);
3705 }
3706
3707 static void vgcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3708 {
3709   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3710   struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data;
3711
3712   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3713     error (g, "%s: failed to parse reply header", "guestfs_vgcreate");
3714     return;
3715   }
3716   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3717     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3718       error (g, "%s: failed to parse reply error", "guestfs_vgcreate");
3719       return;
3720     }
3721     goto done;
3722   }
3723  done:
3724   ctx->cb_sequence = 1001;
3725   ml->main_loop_quit (ml, g);
3726 }
3727
3728 int guestfs_vgcreate (guestfs_h *g,
3729                 const char *volgroup,
3730                 char * const* const physvols)
3731 {
3732   struct guestfs_vgcreate_args args;
3733   struct vgcreate_ctx ctx;
3734   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3735   int serial;
3736
3737   if (check_state (g, "guestfs_vgcreate") == -1) return -1;
3738
3739   memset (&ctx, 0, sizeof ctx);
3740
3741   args.volgroup = (char *) volgroup;
3742   args.physvols.physvols_val = (char **) physvols;
3743   for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ;
3744   serial = guestfs__send (g, GUESTFS_PROC_VGCREATE,
3745         (xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
3746   if (serial == -1)
3747     return -1;
3748
3749   ctx.cb_sequence = 0;
3750   guestfs_set_send_callback (g, vgcreate_send_cb, &ctx);
3751   (void) ml->main_loop_run (ml, g);
3752   guestfs_set_send_callback (g, NULL, NULL);
3753   if (ctx.cb_sequence != 1) {
3754     error (g, "%s send failed, see earlier error messages", "guestfs_vgcreate");
3755     return -1;
3756   }
3757
3758   guestfs__switch_to_receiving (g);
3759   ctx.cb_sequence = 0;
3760   guestfs_set_reply_callback (g, vgcreate_reply_cb, &ctx);
3761   (void) ml->main_loop_run (ml, g);
3762   guestfs_set_reply_callback (g, NULL, NULL);
3763   if (ctx.cb_sequence != 1001) {
3764     error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate");
3765     return -1;
3766   }
3767
3768   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGCREATE, serial) == -1)
3769     return -1;
3770
3771   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3772     error (g, "%s", ctx.err.error_message);
3773     return -1;
3774   }
3775
3776   return 0;
3777 }
3778
3779 struct lvcreate_ctx {
3780   /* This flag is set by the callbacks, so we know we've done
3781    * the callbacks as expected, and in the right sequence.
3782    * 0 = not called, 1 = send called,
3783    * 1001 = reply called.
3784    */
3785   int cb_sequence;
3786   struct guestfs_message_header hdr;
3787   struct guestfs_message_error err;
3788 };
3789
3790 static void lvcreate_send_cb (guestfs_h *g, void *data)
3791 {
3792   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3793   struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data;
3794
3795   ctx->cb_sequence = 1;
3796   ml->main_loop_quit (ml, g);
3797 }
3798
3799 static void lvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3800 {
3801   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3802   struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data;
3803
3804   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3805     error (g, "%s: failed to parse reply header", "guestfs_lvcreate");
3806     return;
3807   }
3808   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3809     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3810       error (g, "%s: failed to parse reply error", "guestfs_lvcreate");
3811       return;
3812     }
3813     goto done;
3814   }
3815  done:
3816   ctx->cb_sequence = 1001;
3817   ml->main_loop_quit (ml, g);
3818 }
3819
3820 int guestfs_lvcreate (guestfs_h *g,
3821                 const char *logvol,
3822                 const char *volgroup,
3823                 int mbytes)
3824 {
3825   struct guestfs_lvcreate_args args;
3826   struct lvcreate_ctx ctx;
3827   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3828   int serial;
3829
3830   if (check_state (g, "guestfs_lvcreate") == -1) return -1;
3831
3832   memset (&ctx, 0, sizeof ctx);
3833
3834   args.logvol = (char *) logvol;
3835   args.volgroup = (char *) volgroup;
3836   args.mbytes = mbytes;
3837   serial = guestfs__send (g, GUESTFS_PROC_LVCREATE,
3838         (xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
3839   if (serial == -1)
3840     return -1;
3841
3842   ctx.cb_sequence = 0;
3843   guestfs_set_send_callback (g, lvcreate_send_cb, &ctx);
3844   (void) ml->main_loop_run (ml, g);
3845   guestfs_set_send_callback (g, NULL, NULL);
3846   if (ctx.cb_sequence != 1) {
3847     error (g, "%s send failed, see earlier error messages", "guestfs_lvcreate");
3848     return -1;
3849   }
3850
3851   guestfs__switch_to_receiving (g);
3852   ctx.cb_sequence = 0;
3853   guestfs_set_reply_callback (g, lvcreate_reply_cb, &ctx);
3854   (void) ml->main_loop_run (ml, g);
3855   guestfs_set_reply_callback (g, NULL, NULL);
3856   if (ctx.cb_sequence != 1001) {
3857     error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate");
3858     return -1;
3859   }
3860
3861   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVCREATE, serial) == -1)
3862     return -1;
3863
3864   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3865     error (g, "%s", ctx.err.error_message);
3866     return -1;
3867   }
3868
3869   return 0;
3870 }
3871
3872 struct mkfs_ctx {
3873   /* This flag is set by the callbacks, so we know we've done
3874    * the callbacks as expected, and in the right sequence.
3875    * 0 = not called, 1 = send called,
3876    * 1001 = reply called.
3877    */
3878   int cb_sequence;
3879   struct guestfs_message_header hdr;
3880   struct guestfs_message_error err;
3881 };
3882
3883 static void mkfs_send_cb (guestfs_h *g, void *data)
3884 {
3885   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3886   struct mkfs_ctx *ctx = (struct mkfs_ctx *) data;
3887
3888   ctx->cb_sequence = 1;
3889   ml->main_loop_quit (ml, g);
3890 }
3891
3892 static void mkfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3893 {
3894   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3895   struct mkfs_ctx *ctx = (struct mkfs_ctx *) data;
3896
3897   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3898     error (g, "%s: failed to parse reply header", "guestfs_mkfs");
3899     return;
3900   }
3901   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3902     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3903       error (g, "%s: failed to parse reply error", "guestfs_mkfs");
3904       return;
3905     }
3906     goto done;
3907   }
3908  done:
3909   ctx->cb_sequence = 1001;
3910   ml->main_loop_quit (ml, g);
3911 }
3912
3913 int guestfs_mkfs (guestfs_h *g,
3914                 const char *fstype,
3915                 const char *device)
3916 {
3917   struct guestfs_mkfs_args args;
3918   struct mkfs_ctx ctx;
3919   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3920   int serial;
3921
3922   if (check_state (g, "guestfs_mkfs") == -1) return -1;
3923
3924   memset (&ctx, 0, sizeof ctx);
3925
3926   args.fstype = (char *) fstype;
3927   args.device = (char *) device;
3928   serial = guestfs__send (g, GUESTFS_PROC_MKFS,
3929         (xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
3930   if (serial == -1)
3931     return -1;
3932
3933   ctx.cb_sequence = 0;
3934   guestfs_set_send_callback (g, mkfs_send_cb, &ctx);
3935   (void) ml->main_loop_run (ml, g);
3936   guestfs_set_send_callback (g, NULL, NULL);
3937   if (ctx.cb_sequence != 1) {
3938     error (g, "%s send failed, see earlier error messages", "guestfs_mkfs");
3939     return -1;
3940   }
3941
3942   guestfs__switch_to_receiving (g);
3943   ctx.cb_sequence = 0;
3944   guestfs_set_reply_callback (g, mkfs_reply_cb, &ctx);
3945   (void) ml->main_loop_run (ml, g);
3946   guestfs_set_reply_callback (g, NULL, NULL);
3947   if (ctx.cb_sequence != 1001) {
3948     error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs");
3949     return -1;
3950   }
3951
3952   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFS, serial) == -1)
3953     return -1;
3954
3955   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3956     error (g, "%s", ctx.err.error_message);
3957     return -1;
3958   }
3959
3960   return 0;
3961 }
3962
3963 struct sfdisk_ctx {
3964   /* This flag is set by the callbacks, so we know we've done
3965    * the callbacks as expected, and in the right sequence.
3966    * 0 = not called, 1 = send called,
3967    * 1001 = reply called.
3968    */
3969   int cb_sequence;
3970   struct guestfs_message_header hdr;
3971   struct guestfs_message_error err;
3972 };
3973
3974 static void sfdisk_send_cb (guestfs_h *g, void *data)
3975 {
3976   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3977   struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data;
3978
3979   ctx->cb_sequence = 1;
3980   ml->main_loop_quit (ml, g);
3981 }
3982
3983 static void sfdisk_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3984 {
3985   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3986   struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data;
3987
3988   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3989     error (g, "%s: failed to parse reply header", "guestfs_sfdisk");
3990     return;
3991   }
3992   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3993     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3994       error (g, "%s: failed to parse reply error", "guestfs_sfdisk");
3995       return;
3996     }
3997     goto done;
3998   }
3999  done:
4000   ctx->cb_sequence = 1001;
4001   ml->main_loop_quit (ml, g);
4002 }
4003
4004 int guestfs_sfdisk (guestfs_h *g,
4005                 const char *device,
4006                 int cyls,
4007                 int heads,
4008                 int sectors,
4009                 char * const* const lines)
4010 {
4011   struct guestfs_sfdisk_args args;
4012   struct sfdisk_ctx ctx;
4013   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4014   int serial;
4015
4016   if (check_state (g, "guestfs_sfdisk") == -1) return -1;
4017
4018   memset (&ctx, 0, sizeof ctx);
4019
4020   args.device = (char *) device;
4021   args.cyls = cyls;
4022   args.heads = heads;
4023   args.sectors = sectors;
4024   args.lines.lines_val = (char **) lines;
4025   for (args.lines.lines_len = 0; lines[args.lines.lines_len]; args.lines.lines_len++) ;
4026   serial = guestfs__send (g, GUESTFS_PROC_SFDISK,
4027         (xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
4028   if (serial == -1)
4029     return -1;
4030
4031   ctx.cb_sequence = 0;
4032   guestfs_set_send_callback (g, sfdisk_send_cb, &ctx);
4033   (void) ml->main_loop_run (ml, g);
4034   guestfs_set_send_callback (g, NULL, NULL);
4035   if (ctx.cb_sequence != 1) {
4036     error (g, "%s send failed, see earlier error messages", "guestfs_sfdisk");
4037     return -1;
4038   }
4039
4040   guestfs__switch_to_receiving (g);
4041   ctx.cb_sequence = 0;
4042   guestfs_set_reply_callback (g, sfdisk_reply_cb, &ctx);
4043   (void) ml->main_loop_run (ml, g);
4044   guestfs_set_reply_callback (g, NULL, NULL);
4045   if (ctx.cb_sequence != 1001) {
4046     error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk");
4047     return -1;
4048   }
4049
4050   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK, serial) == -1)
4051     return -1;
4052
4053   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4054     error (g, "%s", ctx.err.error_message);
4055     return -1;
4056   }
4057
4058   return 0;
4059 }
4060
4061 struct write_file_ctx {
4062   /* This flag is set by the callbacks, so we know we've done
4063    * the callbacks as expected, and in the right sequence.
4064    * 0 = not called, 1 = send called,
4065    * 1001 = reply called.
4066    */
4067   int cb_sequence;
4068   struct guestfs_message_header hdr;
4069   struct guestfs_message_error err;
4070 };
4071
4072 static void write_file_send_cb (guestfs_h *g, void *data)
4073 {
4074   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4075   struct write_file_ctx *ctx = (struct write_file_ctx *) data;
4076
4077   ctx->cb_sequence = 1;
4078   ml->main_loop_quit (ml, g);
4079 }
4080
4081 static void write_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4082 {
4083   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4084   struct write_file_ctx *ctx = (struct write_file_ctx *) data;
4085
4086   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4087     error (g, "%s: failed to parse reply header", "guestfs_write_file");
4088     return;
4089   }
4090   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4091     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4092       error (g, "%s: failed to parse reply error", "guestfs_write_file");
4093       return;
4094     }
4095     goto done;
4096   }
4097  done:
4098   ctx->cb_sequence = 1001;
4099   ml->main_loop_quit (ml, g);
4100 }
4101
4102 int guestfs_write_file (guestfs_h *g,
4103                 const char *path,
4104                 const char *content,
4105                 int size)
4106 {
4107   struct guestfs_write_file_args args;
4108   struct write_file_ctx ctx;
4109   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4110   int serial;
4111
4112   if (check_state (g, "guestfs_write_file") == -1) return -1;
4113
4114   memset (&ctx, 0, sizeof ctx);
4115
4116   args.path = (char *) path;
4117   args.content = (char *) content;
4118   args.size = size;
4119   serial = guestfs__send (g, GUESTFS_PROC_WRITE_FILE,
4120         (xdrproc_t) xdr_guestfs_write_file_args, (char *) &args);
4121   if (serial == -1)
4122     return -1;
4123
4124   ctx.cb_sequence = 0;
4125   guestfs_set_send_callback (g, write_file_send_cb, &ctx);
4126   (void) ml->main_loop_run (ml, g);
4127   guestfs_set_send_callback (g, NULL, NULL);
4128   if (ctx.cb_sequence != 1) {
4129     error (g, "%s send failed, see earlier error messages", "guestfs_write_file");
4130     return -1;
4131   }
4132
4133   guestfs__switch_to_receiving (g);
4134   ctx.cb_sequence = 0;
4135   guestfs_set_reply_callback (g, write_file_reply_cb, &ctx);
4136   (void) ml->main_loop_run (ml, g);
4137   guestfs_set_reply_callback (g, NULL, NULL);
4138   if (ctx.cb_sequence != 1001) {
4139     error (g, "%s reply failed, see earlier error messages", "guestfs_write_file");
4140     return -1;
4141   }
4142
4143   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1)
4144     return -1;
4145
4146   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4147     error (g, "%s", ctx.err.error_message);
4148     return -1;
4149   }
4150
4151   return 0;
4152 }
4153
4154 struct umount_ctx {
4155   /* This flag is set by the callbacks, so we know we've done
4156    * the callbacks as expected, and in the right sequence.
4157    * 0 = not called, 1 = send called,
4158    * 1001 = reply called.
4159    */
4160   int cb_sequence;
4161   struct guestfs_message_header hdr;
4162   struct guestfs_message_error err;
4163 };
4164
4165 static void umount_send_cb (guestfs_h *g, void *data)
4166 {
4167   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4168   struct umount_ctx *ctx = (struct umount_ctx *) data;
4169
4170   ctx->cb_sequence = 1;
4171   ml->main_loop_quit (ml, g);
4172 }
4173
4174 static void umount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4175 {
4176   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4177   struct umount_ctx *ctx = (struct umount_ctx *) data;
4178
4179   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4180     error (g, "%s: failed to parse reply header", "guestfs_umount");
4181     return;
4182   }
4183   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4184     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4185       error (g, "%s: failed to parse reply error", "guestfs_umount");
4186       return;
4187     }
4188     goto done;
4189   }
4190  done:
4191   ctx->cb_sequence = 1001;
4192   ml->main_loop_quit (ml, g);
4193 }
4194
4195 int guestfs_umount (guestfs_h *g,
4196                 const char *pathordevice)
4197 {
4198   struct guestfs_umount_args args;
4199   struct umount_ctx ctx;
4200   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4201   int serial;
4202
4203   if (check_state (g, "guestfs_umount") == -1) return -1;
4204
4205   memset (&ctx, 0, sizeof ctx);
4206
4207   args.pathordevice = (char *) pathordevice;
4208   serial = guestfs__send (g, GUESTFS_PROC_UMOUNT,
4209         (xdrproc_t) xdr_guestfs_umount_args, (char *) &args);
4210   if (serial == -1)
4211     return -1;
4212
4213   ctx.cb_sequence = 0;
4214   guestfs_set_send_callback (g, umount_send_cb, &ctx);
4215   (void) ml->main_loop_run (ml, g);
4216   guestfs_set_send_callback (g, NULL, NULL);
4217   if (ctx.cb_sequence != 1) {
4218     error (g, "%s send failed, see earlier error messages", "guestfs_umount");
4219     return -1;
4220   }
4221
4222   guestfs__switch_to_receiving (g);
4223   ctx.cb_sequence = 0;
4224   guestfs_set_reply_callback (g, umount_reply_cb, &ctx);
4225   (void) ml->main_loop_run (ml, g);
4226   guestfs_set_reply_callback (g, NULL, NULL);
4227   if (ctx.cb_sequence != 1001) {
4228     error (g, "%s reply failed, see earlier error messages", "guestfs_umount");
4229     return -1;
4230   }
4231
4232   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT, serial) == -1)
4233     return -1;
4234
4235   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4236     error (g, "%s", ctx.err.error_message);
4237     return -1;
4238   }
4239
4240   return 0;
4241 }
4242
4243 struct mounts_ctx {
4244   /* This flag is set by the callbacks, so we know we've done
4245    * the callbacks as expected, and in the right sequence.
4246    * 0 = not called, 1 = send called,
4247    * 1001 = reply called.
4248    */
4249   int cb_sequence;
4250   struct guestfs_message_header hdr;
4251   struct guestfs_message_error err;
4252   struct guestfs_mounts_ret ret;
4253 };
4254
4255 static void mounts_send_cb (guestfs_h *g, void *data)
4256 {
4257   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4258   struct mounts_ctx *ctx = (struct mounts_ctx *) data;
4259
4260   ctx->cb_sequence = 1;
4261   ml->main_loop_quit (ml, g);
4262 }
4263
4264 static void mounts_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4265 {
4266   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4267   struct mounts_ctx *ctx = (struct mounts_ctx *) data;
4268
4269   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4270     error (g, "%s: failed to parse reply header", "guestfs_mounts");
4271     return;
4272   }
4273   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4274     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4275       error (g, "%s: failed to parse reply error", "guestfs_mounts");
4276       return;
4277     }
4278     goto done;
4279   }
4280   if (!xdr_guestfs_mounts_ret (xdr, &ctx->ret)) {
4281     error (g, "%s: failed to parse reply", "guestfs_mounts");
4282     return;
4283   }
4284  done:
4285   ctx->cb_sequence = 1001;
4286   ml->main_loop_quit (ml, g);
4287 }
4288
4289 char **guestfs_mounts (guestfs_h *g)
4290 {
4291   struct mounts_ctx ctx;
4292   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4293   int serial;
4294
4295   if (check_state (g, "guestfs_mounts") == -1) return NULL;
4296
4297   memset (&ctx, 0, sizeof ctx);
4298
4299   serial = guestfs__send (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
4300   if (serial == -1)
4301     return NULL;
4302
4303   ctx.cb_sequence = 0;
4304   guestfs_set_send_callback (g, mounts_send_cb, &ctx);
4305   (void) ml->main_loop_run (ml, g);
4306   guestfs_set_send_callback (g, NULL, NULL);
4307   if (ctx.cb_sequence != 1) {
4308     error (g, "%s send failed, see earlier error messages", "guestfs_mounts");
4309     return NULL;
4310   }
4311
4312   guestfs__switch_to_receiving (g);
4313   ctx.cb_sequence = 0;
4314   guestfs_set_reply_callback (g, mounts_reply_cb, &ctx);
4315   (void) ml->main_loop_run (ml, g);
4316   guestfs_set_reply_callback (g, NULL, NULL);
4317   if (ctx.cb_sequence != 1001) {
4318     error (g, "%s reply failed, see earlier error messages", "guestfs_mounts");
4319     return NULL;
4320   }
4321
4322   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNTS, serial) == -1)
4323     return NULL;
4324
4325   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4326     error (g, "%s", ctx.err.error_message);
4327     return NULL;
4328   }
4329
4330   /* caller will free this, but we need to add a NULL entry */
4331   ctx.ret.devices.devices_val =
4332     safe_realloc (g, ctx.ret.devices.devices_val,
4333                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
4334   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
4335   return ctx.ret.devices.devices_val;
4336 }
4337
4338 struct umount_all_ctx {
4339   /* This flag is set by the callbacks, so we know we've done
4340    * the callbacks as expected, and in the right sequence.
4341    * 0 = not called, 1 = send called,
4342    * 1001 = reply called.
4343    */
4344   int cb_sequence;
4345   struct guestfs_message_header hdr;
4346   struct guestfs_message_error err;
4347 };
4348
4349 static void umount_all_send_cb (guestfs_h *g, void *data)
4350 {
4351   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4352   struct umount_all_ctx *ctx = (struct umount_all_ctx *) data;
4353
4354   ctx->cb_sequence = 1;
4355   ml->main_loop_quit (ml, g);
4356 }
4357
4358 static void umount_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4359 {
4360   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4361   struct umount_all_ctx *ctx = (struct umount_all_ctx *) data;
4362
4363   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4364     error (g, "%s: failed to parse reply header", "guestfs_umount_all");
4365     return;
4366   }
4367   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4368     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4369       error (g, "%s: failed to parse reply error", "guestfs_umount_all");
4370       return;
4371     }
4372     goto done;
4373   }
4374  done:
4375   ctx->cb_sequence = 1001;
4376   ml->main_loop_quit (ml, g);
4377 }
4378
4379 int guestfs_umount_all (guestfs_h *g)
4380 {
4381   struct umount_all_ctx ctx;
4382   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4383   int serial;
4384
4385   if (check_state (g, "guestfs_umount_all") == -1) return -1;
4386
4387   memset (&ctx, 0, sizeof ctx);
4388
4389   serial = guestfs__send (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
4390   if (serial == -1)
4391     return -1;
4392
4393   ctx.cb_sequence = 0;
4394   guestfs_set_send_callback (g, umount_all_send_cb, &ctx);
4395   (void) ml->main_loop_run (ml, g);
4396   guestfs_set_send_callback (g, NULL, NULL);
4397   if (ctx.cb_sequence != 1) {
4398     error (g, "%s send failed, see earlier error messages", "guestfs_umount_all");
4399     return -1;
4400   }
4401
4402   guestfs__switch_to_receiving (g);
4403   ctx.cb_sequence = 0;
4404   guestfs_set_reply_callback (g, umount_all_reply_cb, &ctx);
4405   (void) ml->main_loop_run (ml, g);
4406   guestfs_set_reply_callback (g, NULL, NULL);
4407   if (ctx.cb_sequence != 1001) {
4408     error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all");
4409     return -1;
4410   }
4411
4412   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1)
4413     return -1;
4414
4415   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4416     error (g, "%s", ctx.err.error_message);
4417     return -1;
4418   }
4419
4420   return 0;
4421 }
4422
4423 struct lvm_remove_all_ctx {
4424   /* This flag is set by the callbacks, so we know we've done
4425    * the callbacks as expected, and in the right sequence.
4426    * 0 = not called, 1 = send called,
4427    * 1001 = reply called.
4428    */
4429   int cb_sequence;
4430   struct guestfs_message_header hdr;
4431   struct guestfs_message_error err;
4432 };
4433
4434 static void lvm_remove_all_send_cb (guestfs_h *g, void *data)
4435 {
4436   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4437   struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data;
4438
4439   ctx->cb_sequence = 1;
4440   ml->main_loop_quit (ml, g);
4441 }
4442
4443 static void lvm_remove_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4444 {
4445   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4446   struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data;
4447
4448   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4449     error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all");
4450     return;
4451   }
4452   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4453     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4454       error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all");
4455       return;
4456     }
4457     goto done;
4458   }
4459  done:
4460   ctx->cb_sequence = 1001;
4461   ml->main_loop_quit (ml, g);
4462 }
4463
4464 int guestfs_lvm_remove_all (guestfs_h *g)
4465 {
4466   struct lvm_remove_all_ctx ctx;
4467   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4468   int serial;
4469
4470   if (check_state (g, "guestfs_lvm_remove_all") == -1) return -1;
4471
4472   memset (&ctx, 0, sizeof ctx);
4473
4474   serial = guestfs__send (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
4475   if (serial == -1)
4476     return -1;
4477
4478   ctx.cb_sequence = 0;
4479   guestfs_set_send_callback (g, lvm_remove_all_send_cb, &ctx);
4480   (void) ml->main_loop_run (ml, g);
4481   guestfs_set_send_callback (g, NULL, NULL);
4482   if (ctx.cb_sequence != 1) {
4483     error (g, "%s send failed, see earlier error messages", "guestfs_lvm_remove_all");
4484     return -1;
4485   }
4486
4487   guestfs__switch_to_receiving (g);
4488   ctx.cb_sequence = 0;
4489   guestfs_set_reply_callback (g, lvm_remove_all_reply_cb, &ctx);
4490   (void) ml->main_loop_run (ml, g);
4491   guestfs_set_reply_callback (g, NULL, NULL);
4492   if (ctx.cb_sequence != 1001) {
4493     error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all");
4494     return -1;
4495   }
4496
4497   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1)
4498     return -1;
4499
4500   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4501     error (g, "%s", ctx.err.error_message);
4502     return -1;
4503   }
4504
4505   return 0;
4506 }
4507
4508 struct file_ctx {
4509   /* This flag is set by the callbacks, so we know we've done
4510    * the callbacks as expected, and in the right sequence.
4511    * 0 = not called, 1 = send called,
4512    * 1001 = reply called.
4513    */
4514   int cb_sequence;
4515   struct guestfs_message_header hdr;
4516   struct guestfs_message_error err;
4517   struct guestfs_file_ret ret;
4518 };
4519
4520 static void file_send_cb (guestfs_h *g, void *data)
4521 {
4522   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4523   struct file_ctx *ctx = (struct file_ctx *) data;
4524
4525   ctx->cb_sequence = 1;
4526   ml->main_loop_quit (ml, g);
4527 }
4528
4529 static void file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4530 {
4531   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4532   struct file_ctx *ctx = (struct file_ctx *) data;
4533
4534   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4535     error (g, "%s: failed to parse reply header", "guestfs_file");
4536     return;
4537   }
4538   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4539     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4540       error (g, "%s: failed to parse reply error", "guestfs_file");
4541       return;
4542     }
4543     goto done;
4544   }
4545   if (!xdr_guestfs_file_ret (xdr, &ctx->ret)) {
4546     error (g, "%s: failed to parse reply", "guestfs_file");
4547     return;
4548   }
4549  done:
4550   ctx->cb_sequence = 1001;
4551   ml->main_loop_quit (ml, g);
4552 }
4553
4554 char *guestfs_file (guestfs_h *g,
4555                 const char *path)
4556 {
4557   struct guestfs_file_args args;
4558   struct file_ctx ctx;
4559   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4560   int serial;
4561
4562   if (check_state (g, "guestfs_file") == -1) return NULL;
4563
4564   memset (&ctx, 0, sizeof ctx);
4565
4566   args.path = (char *) path;
4567   serial = guestfs__send (g, GUESTFS_PROC_FILE,
4568         (xdrproc_t) xdr_guestfs_file_args, (char *) &args);
4569   if (serial == -1)
4570     return NULL;
4571
4572   ctx.cb_sequence = 0;
4573   guestfs_set_send_callback (g, file_send_cb, &ctx);
4574   (void) ml->main_loop_run (ml, g);
4575   guestfs_set_send_callback (g, NULL, NULL);
4576   if (ctx.cb_sequence != 1) {
4577     error (g, "%s send failed, see earlier error messages", "guestfs_file");
4578     return NULL;
4579   }
4580
4581   guestfs__switch_to_receiving (g);
4582   ctx.cb_sequence = 0;
4583   guestfs_set_reply_callback (g, file_reply_cb, &ctx);
4584   (void) ml->main_loop_run (ml, g);
4585   guestfs_set_reply_callback (g, NULL, NULL);
4586   if (ctx.cb_sequence != 1001) {
4587     error (g, "%s reply failed, see earlier error messages", "guestfs_file");
4588     return NULL;
4589   }
4590
4591   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FILE, serial) == -1)
4592     return NULL;
4593
4594   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4595     error (g, "%s", ctx.err.error_message);
4596     return NULL;
4597   }
4598
4599   return ctx.ret.description; /* caller will free */
4600 }
4601
4602 struct command_ctx {
4603   /* This flag is set by the callbacks, so we know we've done
4604    * the callbacks as expected, and in the right sequence.
4605    * 0 = not called, 1 = send called,
4606    * 1001 = reply called.
4607    */
4608   int cb_sequence;
4609   struct guestfs_message_header hdr;
4610   struct guestfs_message_error err;
4611   struct guestfs_command_ret ret;
4612 };
4613
4614 static void command_send_cb (guestfs_h *g, void *data)
4615 {
4616   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4617   struct command_ctx *ctx = (struct command_ctx *) data;
4618
4619   ctx->cb_sequence = 1;
4620   ml->main_loop_quit (ml, g);
4621 }
4622
4623 static void command_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4624 {
4625   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4626   struct command_ctx *ctx = (struct command_ctx *) data;
4627
4628   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4629     error (g, "%s: failed to parse reply header", "guestfs_command");
4630     return;
4631   }
4632   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4633     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4634       error (g, "%s: failed to parse reply error", "guestfs_command");
4635       return;
4636     }
4637     goto done;
4638   }
4639   if (!xdr_guestfs_command_ret (xdr, &ctx->ret)) {
4640     error (g, "%s: failed to parse reply", "guestfs_command");
4641     return;
4642   }
4643  done:
4644   ctx->cb_sequence = 1001;
4645   ml->main_loop_quit (ml, g);
4646 }
4647
4648 char *guestfs_command (guestfs_h *g,
4649                 char * const* const arguments)
4650 {
4651   struct guestfs_command_args args;
4652   struct command_ctx ctx;
4653   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4654   int serial;
4655
4656   if (check_state (g, "guestfs_command") == -1) return NULL;
4657
4658   memset (&ctx, 0, sizeof ctx);
4659
4660   args.arguments.arguments_val = (char **) arguments;
4661   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4662   serial = guestfs__send (g, GUESTFS_PROC_COMMAND,
4663         (xdrproc_t) xdr_guestfs_command_args, (char *) &args);
4664   if (serial == -1)
4665     return NULL;
4666
4667   ctx.cb_sequence = 0;
4668   guestfs_set_send_callback (g, command_send_cb, &ctx);
4669   (void) ml->main_loop_run (ml, g);
4670   guestfs_set_send_callback (g, NULL, NULL);
4671   if (ctx.cb_sequence != 1) {
4672     error (g, "%s send failed, see earlier error messages", "guestfs_command");
4673     return NULL;
4674   }
4675
4676   guestfs__switch_to_receiving (g);
4677   ctx.cb_sequence = 0;
4678   guestfs_set_reply_callback (g, command_reply_cb, &ctx);
4679   (void) ml->main_loop_run (ml, g);
4680   guestfs_set_reply_callback (g, NULL, NULL);
4681   if (ctx.cb_sequence != 1001) {
4682     error (g, "%s reply failed, see earlier error messages", "guestfs_command");
4683     return NULL;
4684   }
4685
4686   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND, serial) == -1)
4687     return NULL;
4688
4689   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4690     error (g, "%s", ctx.err.error_message);
4691     return NULL;
4692   }
4693
4694   return ctx.ret.output; /* caller will free */
4695 }
4696
4697 struct command_lines_ctx {
4698   /* This flag is set by the callbacks, so we know we've done
4699    * the callbacks as expected, and in the right sequence.
4700    * 0 = not called, 1 = send called,
4701    * 1001 = reply called.
4702    */
4703   int cb_sequence;
4704   struct guestfs_message_header hdr;
4705   struct guestfs_message_error err;
4706   struct guestfs_command_lines_ret ret;
4707 };
4708
4709 static void command_lines_send_cb (guestfs_h *g, void *data)
4710 {
4711   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4712   struct command_lines_ctx *ctx = (struct command_lines_ctx *) data;
4713
4714   ctx->cb_sequence = 1;
4715   ml->main_loop_quit (ml, g);
4716 }
4717
4718 static void command_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4719 {
4720   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4721   struct command_lines_ctx *ctx = (struct command_lines_ctx *) data;
4722
4723   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4724     error (g, "%s: failed to parse reply header", "guestfs_command_lines");
4725     return;
4726   }
4727   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4728     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4729       error (g, "%s: failed to parse reply error", "guestfs_command_lines");
4730       return;
4731     }
4732     goto done;
4733   }
4734   if (!xdr_guestfs_command_lines_ret (xdr, &ctx->ret)) {
4735     error (g, "%s: failed to parse reply", "guestfs_command_lines");
4736     return;
4737   }
4738  done:
4739   ctx->cb_sequence = 1001;
4740   ml->main_loop_quit (ml, g);
4741 }
4742
4743 char **guestfs_command_lines (guestfs_h *g,
4744                 char * const* const arguments)
4745 {
4746   struct guestfs_command_lines_args args;
4747   struct command_lines_ctx ctx;
4748   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4749   int serial;
4750
4751   if (check_state (g, "guestfs_command_lines") == -1) return NULL;
4752
4753   memset (&ctx, 0, sizeof ctx);
4754
4755   args.arguments.arguments_val = (char **) arguments;
4756   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4757   serial = guestfs__send (g, GUESTFS_PROC_COMMAND_LINES,
4758         (xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args);
4759   if (serial == -1)
4760     return NULL;
4761
4762   ctx.cb_sequence = 0;
4763   guestfs_set_send_callback (g, command_lines_send_cb, &ctx);
4764   (void) ml->main_loop_run (ml, g);
4765   guestfs_set_send_callback (g, NULL, NULL);
4766   if (ctx.cb_sequence != 1) {
4767     error (g, "%s send failed, see earlier error messages", "guestfs_command_lines");
4768     return NULL;
4769   }
4770
4771   guestfs__switch_to_receiving (g);
4772   ctx.cb_sequence = 0;
4773   guestfs_set_reply_callback (g, command_lines_reply_cb, &ctx);
4774   (void) ml->main_loop_run (ml, g);
4775   guestfs_set_reply_callback (g, NULL, NULL);
4776   if (ctx.cb_sequence != 1001) {
4777     error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines");
4778     return NULL;
4779   }
4780
4781   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1)
4782     return NULL;
4783
4784   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4785     error (g, "%s", ctx.err.error_message);
4786     return NULL;
4787   }
4788
4789   /* caller will free this, but we need to add a NULL entry */
4790   ctx.ret.lines.lines_val =
4791     safe_realloc (g, ctx.ret.lines.lines_val,
4792                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
4793   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
4794   return ctx.ret.lines.lines_val;
4795 }
4796
4797 struct stat_ctx {
4798   /* This flag is set by the callbacks, so we know we've done
4799    * the callbacks as expected, and in the right sequence.
4800    * 0 = not called, 1 = send called,
4801    * 1001 = reply called.
4802    */
4803   int cb_sequence;
4804   struct guestfs_message_header hdr;
4805   struct guestfs_message_error err;
4806   struct guestfs_stat_ret ret;
4807 };
4808
4809 static void stat_send_cb (guestfs_h *g, void *data)
4810 {
4811   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4812   struct stat_ctx *ctx = (struct stat_ctx *) data;
4813
4814   ctx->cb_sequence = 1;
4815   ml->main_loop_quit (ml, g);
4816 }
4817
4818 static void stat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4819 {
4820   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4821   struct stat_ctx *ctx = (struct stat_ctx *) data;
4822
4823   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4824     error (g, "%s: failed to parse reply header", "guestfs_stat");
4825     return;
4826   }
4827   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4828     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4829       error (g, "%s: failed to parse reply error", "guestfs_stat");
4830       return;
4831     }
4832     goto done;
4833   }
4834   if (!xdr_guestfs_stat_ret (xdr, &ctx->ret)) {
4835     error (g, "%s: failed to parse reply", "guestfs_stat");
4836     return;
4837   }
4838  done:
4839   ctx->cb_sequence = 1001;
4840   ml->main_loop_quit (ml, g);
4841 }
4842
4843 struct guestfs_stat *guestfs_stat (guestfs_h *g,
4844                 const char *path)
4845 {
4846   struct guestfs_stat_args args;
4847   struct stat_ctx ctx;
4848   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4849   int serial;
4850
4851   if (check_state (g, "guestfs_stat") == -1) return NULL;
4852
4853   memset (&ctx, 0, sizeof ctx);
4854
4855   args.path = (char *) path;
4856   serial = guestfs__send (g, GUESTFS_PROC_STAT,
4857         (xdrproc_t) xdr_guestfs_stat_args, (char *) &args);
4858   if (serial == -1)
4859     return NULL;
4860
4861   ctx.cb_sequence = 0;
4862   guestfs_set_send_callback (g, stat_send_cb, &ctx);
4863   (void) ml->main_loop_run (ml, g);
4864   guestfs_set_send_callback (g, NULL, NULL);
4865   if (ctx.cb_sequence != 1) {
4866     error (g, "%s send failed, see earlier error messages", "guestfs_stat");
4867     return NULL;
4868   }
4869
4870   guestfs__switch_to_receiving (g);
4871   ctx.cb_sequence = 0;
4872   guestfs_set_reply_callback (g, stat_reply_cb, &ctx);
4873   (void) ml->main_loop_run (ml, g);
4874   guestfs_set_reply_callback (g, NULL, NULL);
4875   if (ctx.cb_sequence != 1001) {
4876     error (g, "%s reply failed, see earlier error messages", "guestfs_stat");
4877     return NULL;
4878   }
4879
4880   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STAT, serial) == -1)
4881     return NULL;
4882
4883   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4884     error (g, "%s", ctx.err.error_message);
4885     return NULL;
4886   }
4887
4888   /* caller will free this */
4889   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4890 }
4891
4892 struct lstat_ctx {
4893   /* This flag is set by the callbacks, so we know we've done
4894    * the callbacks as expected, and in the right sequence.
4895    * 0 = not called, 1 = send called,
4896    * 1001 = reply called.
4897    */
4898   int cb_sequence;
4899   struct guestfs_message_header hdr;
4900   struct guestfs_message_error err;
4901   struct guestfs_lstat_ret ret;
4902 };
4903
4904 static void lstat_send_cb (guestfs_h *g, void *data)
4905 {
4906   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4907   struct lstat_ctx *ctx = (struct lstat_ctx *) data;
4908
4909   ctx->cb_sequence = 1;
4910   ml->main_loop_quit (ml, g);
4911 }
4912
4913 static void lstat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4914 {
4915   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4916   struct lstat_ctx *ctx = (struct lstat_ctx *) data;
4917
4918   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4919     error (g, "%s: failed to parse reply header", "guestfs_lstat");
4920     return;
4921   }
4922   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4923     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4924       error (g, "%s: failed to parse reply error", "guestfs_lstat");
4925       return;
4926     }
4927     goto done;
4928   }
4929   if (!xdr_guestfs_lstat_ret (xdr, &ctx->ret)) {
4930     error (g, "%s: failed to parse reply", "guestfs_lstat");
4931     return;
4932   }
4933  done:
4934   ctx->cb_sequence = 1001;
4935   ml->main_loop_quit (ml, g);
4936 }
4937
4938 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
4939                 const char *path)
4940 {
4941   struct guestfs_lstat_args args;
4942   struct lstat_ctx ctx;
4943   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4944   int serial;
4945
4946   if (check_state (g, "guestfs_lstat") == -1) return NULL;
4947
4948   memset (&ctx, 0, sizeof ctx);
4949
4950   args.path = (char *) path;
4951   serial = guestfs__send (g, GUESTFS_PROC_LSTAT,
4952         (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args);
4953   if (serial == -1)
4954     return NULL;
4955
4956   ctx.cb_sequence = 0;
4957   guestfs_set_send_callback (g, lstat_send_cb, &ctx);
4958   (void) ml->main_loop_run (ml, g);
4959   guestfs_set_send_callback (g, NULL, NULL);
4960   if (ctx.cb_sequence != 1) {
4961     error (g, "%s send failed, see earlier error messages", "guestfs_lstat");
4962     return NULL;
4963   }
4964
4965   guestfs__switch_to_receiving (g);
4966   ctx.cb_sequence = 0;
4967   guestfs_set_reply_callback (g, lstat_reply_cb, &ctx);
4968   (void) ml->main_loop_run (ml, g);
4969   guestfs_set_reply_callback (g, NULL, NULL);
4970   if (ctx.cb_sequence != 1001) {
4971     error (g, "%s reply failed, see earlier error messages", "guestfs_lstat");
4972     return NULL;
4973   }
4974
4975   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LSTAT, serial) == -1)
4976     return NULL;
4977
4978   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4979     error (g, "%s", ctx.err.error_message);
4980     return NULL;
4981   }
4982
4983   /* caller will free this */
4984   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4985 }
4986
4987 struct statvfs_ctx {
4988   /* This flag is set by the callbacks, so we know we've done
4989    * the callbacks as expected, and in the right sequence.
4990    * 0 = not called, 1 = send called,
4991    * 1001 = reply called.
4992    */
4993   int cb_sequence;
4994   struct guestfs_message_header hdr;
4995   struct guestfs_message_error err;
4996   struct guestfs_statvfs_ret ret;
4997 };
4998
4999 static void statvfs_send_cb (guestfs_h *g, void *data)
5000 {
5001   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5002   struct statvfs_ctx *ctx = (struct statvfs_ctx *) data;
5003
5004   ctx->cb_sequence = 1;
5005   ml->main_loop_quit (ml, g);
5006 }
5007
5008 static void statvfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5009 {
5010   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5011   struct statvfs_ctx *ctx = (struct statvfs_ctx *) data;
5012
5013   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5014     error (g, "%s: failed to parse reply header", "guestfs_statvfs");
5015     return;
5016   }
5017   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5018     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5019       error (g, "%s: failed to parse reply error", "guestfs_statvfs");
5020       return;
5021     }
5022     goto done;
5023   }
5024   if (!xdr_guestfs_statvfs_ret (xdr, &ctx->ret)) {
5025     error (g, "%s: failed to parse reply", "guestfs_statvfs");
5026     return;
5027   }
5028  done:
5029   ctx->cb_sequence = 1001;
5030   ml->main_loop_quit (ml, g);
5031 }
5032
5033 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
5034                 const char *path)
5035 {
5036   struct guestfs_statvfs_args args;
5037   struct statvfs_ctx ctx;
5038   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5039   int serial;
5040
5041   if (check_state (g, "guestfs_statvfs") == -1) return NULL;
5042
5043   memset (&ctx, 0, sizeof ctx);
5044
5045   args.path = (char *) path;
5046   serial = guestfs__send (g, GUESTFS_PROC_STATVFS,
5047         (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args);
5048   if (serial == -1)
5049     return NULL;
5050
5051   ctx.cb_sequence = 0;
5052   guestfs_set_send_callback (g, statvfs_send_cb, &ctx);
5053   (void) ml->main_loop_run (ml, g);
5054   guestfs_set_send_callback (g, NULL, NULL);
5055   if (ctx.cb_sequence != 1) {
5056     error (g, "%s send failed, see earlier error messages", "guestfs_statvfs");
5057     return NULL;
5058   }
5059
5060   guestfs__switch_to_receiving (g);
5061   ctx.cb_sequence = 0;
5062   guestfs_set_reply_callback (g, statvfs_reply_cb, &ctx);
5063   (void) ml->main_loop_run (ml, g);
5064   guestfs_set_reply_callback (g, NULL, NULL);
5065   if (ctx.cb_sequence != 1001) {
5066     error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs");
5067     return NULL;
5068   }
5069
5070   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STATVFS, serial) == -1)
5071     return NULL;
5072
5073   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5074     error (g, "%s", ctx.err.error_message);
5075     return NULL;
5076   }
5077
5078   /* caller will free this */
5079   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
5080 }
5081
5082 struct tune2fs_l_ctx {
5083   /* This flag is set by the callbacks, so we know we've done
5084    * the callbacks as expected, and in the right sequence.
5085    * 0 = not called, 1 = send called,
5086    * 1001 = reply called.
5087    */
5088   int cb_sequence;
5089   struct guestfs_message_header hdr;
5090   struct guestfs_message_error err;
5091   struct guestfs_tune2fs_l_ret ret;
5092 };
5093
5094 static void tune2fs_l_send_cb (guestfs_h *g, void *data)
5095 {
5096   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5097   struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data;
5098
5099   ctx->cb_sequence = 1;
5100   ml->main_loop_quit (ml, g);
5101 }
5102
5103 static void tune2fs_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5104 {
5105   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5106   struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data;
5107
5108   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5109     error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l");
5110     return;
5111   }
5112   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5113     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5114       error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l");
5115       return;
5116     }
5117     goto done;
5118   }
5119   if (!xdr_guestfs_tune2fs_l_ret (xdr, &ctx->ret)) {
5120     error (g, "%s: failed to parse reply", "guestfs_tune2fs_l");
5121     return;
5122   }
5123  done:
5124   ctx->cb_sequence = 1001;
5125   ml->main_loop_quit (ml, g);
5126 }
5127
5128 char **guestfs_tune2fs_l (guestfs_h *g,
5129                 const char *device)
5130 {
5131   struct guestfs_tune2fs_l_args args;
5132   struct tune2fs_l_ctx ctx;
5133   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5134   int serial;
5135
5136   if (check_state (g, "guestfs_tune2fs_l") == -1) return NULL;
5137
5138   memset (&ctx, 0, sizeof ctx);
5139
5140   args.device = (char *) device;
5141   serial = guestfs__send (g, GUESTFS_PROC_TUNE2FS_L,
5142         (xdrproc_t) xdr_guestfs_tune2fs_l_args, (char *) &args);
5143   if (serial == -1)
5144     return NULL;
5145
5146   ctx.cb_sequence = 0;
5147   guestfs_set_send_callback (g, tune2fs_l_send_cb, &ctx);
5148   (void) ml->main_loop_run (ml, g);
5149   guestfs_set_send_callback (g, NULL, NULL);
5150   if (ctx.cb_sequence != 1) {
5151     error (g, "%s send failed, see earlier error messages", "guestfs_tune2fs_l");
5152     return NULL;
5153   }
5154
5155   guestfs__switch_to_receiving (g);
5156   ctx.cb_sequence = 0;
5157   guestfs_set_reply_callback (g, tune2fs_l_reply_cb, &ctx);
5158   (void) ml->main_loop_run (ml, g);
5159   guestfs_set_reply_callback (g, NULL, NULL);
5160   if (ctx.cb_sequence != 1001) {
5161     error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l");
5162     return NULL;
5163   }
5164
5165   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1)
5166     return NULL;
5167
5168   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5169     error (g, "%s", ctx.err.error_message);
5170     return NULL;
5171   }
5172
5173   /* caller will free this, but we need to add a NULL entry */
5174   ctx.ret.superblock.superblock_val =
5175     safe_realloc (g, ctx.ret.superblock.superblock_val,
5176                   sizeof (char *) * (ctx.ret.superblock.superblock_len + 1));
5177   ctx.ret.superblock.superblock_val[ctx.ret.superblock.superblock_len] = NULL;
5178   return ctx.ret.superblock.superblock_val;
5179 }
5180
5181 struct blockdev_setro_ctx {
5182   /* This flag is set by the callbacks, so we know we've done
5183    * the callbacks as expected, and in the right sequence.
5184    * 0 = not called, 1 = send called,
5185    * 1001 = reply called.
5186    */
5187   int cb_sequence;
5188   struct guestfs_message_header hdr;
5189   struct guestfs_message_error err;
5190 };
5191
5192 static void blockdev_setro_send_cb (guestfs_h *g, void *data)
5193 {
5194   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5195   struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data;
5196
5197   ctx->cb_sequence = 1;
5198   ml->main_loop_quit (ml, g);
5199 }
5200
5201 static void blockdev_setro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5202 {
5203   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5204   struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data;
5205
5206   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5207     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro");
5208     return;
5209   }
5210   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5211     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5212       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro");
5213       return;
5214     }
5215     goto done;
5216   }
5217  done:
5218   ctx->cb_sequence = 1001;
5219   ml->main_loop_quit (ml, g);
5220 }
5221
5222 int guestfs_blockdev_setro (guestfs_h *g,
5223                 const char *device)
5224 {
5225   struct guestfs_blockdev_setro_args args;
5226   struct blockdev_setro_ctx ctx;
5227   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5228   int serial;
5229
5230   if (check_state (g, "guestfs_blockdev_setro") == -1) return -1;
5231
5232   memset (&ctx, 0, sizeof ctx);
5233
5234   args.device = (char *) device;
5235   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_SETRO,
5236         (xdrproc_t) xdr_guestfs_blockdev_setro_args, (char *) &args);
5237   if (serial == -1)
5238     return -1;
5239
5240   ctx.cb_sequence = 0;
5241   guestfs_set_send_callback (g, blockdev_setro_send_cb, &ctx);
5242   (void) ml->main_loop_run (ml, g);
5243   guestfs_set_send_callback (g, NULL, NULL);
5244   if (ctx.cb_sequence != 1) {
5245     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_setro");
5246     return -1;
5247   }
5248
5249   guestfs__switch_to_receiving (g);
5250   ctx.cb_sequence = 0;
5251   guestfs_set_reply_callback (g, blockdev_setro_reply_cb, &ctx);
5252   (void) ml->main_loop_run (ml, g);
5253   guestfs_set_reply_callback (g, NULL, NULL);
5254   if (ctx.cb_sequence != 1001) {
5255     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro");
5256     return -1;
5257   }
5258
5259   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1)
5260     return -1;
5261
5262   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5263     error (g, "%s", ctx.err.error_message);
5264     return -1;
5265   }
5266
5267   return 0;
5268 }
5269
5270 struct blockdev_setrw_ctx {
5271   /* This flag is set by the callbacks, so we know we've done
5272    * the callbacks as expected, and in the right sequence.
5273    * 0 = not called, 1 = send called,
5274    * 1001 = reply called.
5275    */
5276   int cb_sequence;
5277   struct guestfs_message_header hdr;
5278   struct guestfs_message_error err;
5279 };
5280
5281 static void blockdev_setrw_send_cb (guestfs_h *g, void *data)
5282 {
5283   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5284   struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data;
5285
5286   ctx->cb_sequence = 1;
5287   ml->main_loop_quit (ml, g);
5288 }
5289
5290 static void blockdev_setrw_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5291 {
5292   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5293   struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data;
5294
5295   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5296     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw");
5297     return;
5298   }
5299   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5300     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5301       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw");
5302       return;
5303     }
5304     goto done;
5305   }
5306  done:
5307   ctx->cb_sequence = 1001;
5308   ml->main_loop_quit (ml, g);
5309 }
5310
5311 int guestfs_blockdev_setrw (guestfs_h *g,
5312                 const char *device)
5313 {
5314   struct guestfs_blockdev_setrw_args args;
5315   struct blockdev_setrw_ctx ctx;
5316   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5317   int serial;
5318
5319   if (check_state (g, "guestfs_blockdev_setrw") == -1) return -1;
5320
5321   memset (&ctx, 0, sizeof ctx);
5322
5323   args.device = (char *) device;
5324   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_SETRW,
5325         (xdrproc_t) xdr_guestfs_blockdev_setrw_args, (char *) &args);
5326   if (serial == -1)
5327     return -1;
5328
5329   ctx.cb_sequence = 0;
5330   guestfs_set_send_callback (g, blockdev_setrw_send_cb, &ctx);
5331   (void) ml->main_loop_run (ml, g);
5332   guestfs_set_send_callback (g, NULL, NULL);
5333   if (ctx.cb_sequence != 1) {
5334     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_setrw");
5335     return -1;
5336   }
5337
5338   guestfs__switch_to_receiving (g);
5339   ctx.cb_sequence = 0;
5340   guestfs_set_reply_callback (g, blockdev_setrw_reply_cb, &ctx);
5341   (void) ml->main_loop_run (ml, g);
5342   guestfs_set_reply_callback (g, NULL, NULL);
5343   if (ctx.cb_sequence != 1001) {
5344     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw");
5345     return -1;
5346   }
5347
5348   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1)
5349     return -1;
5350
5351   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5352     error (g, "%s", ctx.err.error_message);
5353     return -1;
5354   }
5355
5356   return 0;
5357 }
5358
5359 struct blockdev_getro_ctx {
5360   /* This flag is set by the callbacks, so we know we've done
5361    * the callbacks as expected, and in the right sequence.
5362    * 0 = not called, 1 = send called,
5363    * 1001 = reply called.
5364    */
5365   int cb_sequence;
5366   struct guestfs_message_header hdr;
5367   struct guestfs_message_error err;
5368   struct guestfs_blockdev_getro_ret ret;
5369 };
5370
5371 static void blockdev_getro_send_cb (guestfs_h *g, void *data)
5372 {
5373   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5374   struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data;
5375
5376   ctx->cb_sequence = 1;
5377   ml->main_loop_quit (ml, g);
5378 }
5379
5380 static void blockdev_getro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5381 {
5382   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5383   struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data;
5384
5385   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5386     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro");
5387     return;
5388   }
5389   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5390     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5391       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro");
5392       return;
5393     }
5394     goto done;
5395   }
5396   if (!xdr_guestfs_blockdev_getro_ret (xdr, &ctx->ret)) {
5397     error (g, "%s: failed to parse reply", "guestfs_blockdev_getro");
5398     return;
5399   }
5400  done:
5401   ctx->cb_sequence = 1001;
5402   ml->main_loop_quit (ml, g);
5403 }
5404
5405 int guestfs_blockdev_getro (guestfs_h *g,
5406                 const char *device)
5407 {
5408   struct guestfs_blockdev_getro_args args;
5409   struct blockdev_getro_ctx ctx;
5410   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5411   int serial;
5412
5413   if (check_state (g, "guestfs_blockdev_getro") == -1) return -1;
5414
5415   memset (&ctx, 0, sizeof ctx);
5416
5417   args.device = (char *) device;
5418   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_GETRO,
5419         (xdrproc_t) xdr_guestfs_blockdev_getro_args, (char *) &args);
5420   if (serial == -1)
5421     return -1;
5422
5423   ctx.cb_sequence = 0;
5424   guestfs_set_send_callback (g, blockdev_getro_send_cb, &ctx);
5425   (void) ml->main_loop_run (ml, g);
5426   guestfs_set_send_callback (g, NULL, NULL);
5427   if (ctx.cb_sequence != 1) {
5428     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_getro");
5429     return -1;
5430   }
5431
5432   guestfs__switch_to_receiving (g);
5433   ctx.cb_sequence = 0;
5434   guestfs_set_reply_callback (g, blockdev_getro_reply_cb, &ctx);
5435   (void) ml->main_loop_run (ml, g);
5436   guestfs_set_reply_callback (g, NULL, NULL);
5437   if (ctx.cb_sequence != 1001) {
5438     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro");
5439     return -1;
5440   }
5441
5442   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1)
5443     return -1;
5444
5445   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5446     error (g, "%s", ctx.err.error_message);
5447     return -1;
5448   }
5449
5450   return ctx.ret.ro;
5451 }
5452
5453 struct blockdev_getss_ctx {
5454   /* This flag is set by the callbacks, so we know we've done
5455    * the callbacks as expected, and in the right sequence.
5456    * 0 = not called, 1 = send called,
5457    * 1001 = reply called.
5458    */
5459   int cb_sequence;
5460   struct guestfs_message_header hdr;
5461   struct guestfs_message_error err;
5462   struct guestfs_blockdev_getss_ret ret;
5463 };
5464
5465 static void blockdev_getss_send_cb (guestfs_h *g, void *data)
5466 {
5467   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5468   struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data;
5469
5470   ctx->cb_sequence = 1;
5471   ml->main_loop_quit (ml, g);
5472 }
5473
5474 static void blockdev_getss_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5475 {
5476   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5477   struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data;
5478
5479   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5480     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss");
5481     return;
5482   }
5483   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5484     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5485       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss");
5486       return;
5487     }
5488     goto done;
5489   }
5490   if (!xdr_guestfs_blockdev_getss_ret (xdr, &ctx->ret)) {
5491     error (g, "%s: failed to parse reply", "guestfs_blockdev_getss");
5492     return;
5493   }
5494  done:
5495   ctx->cb_sequence = 1001;
5496   ml->main_loop_quit (ml, g);
5497 }
5498
5499 int guestfs_blockdev_getss (guestfs_h *g,
5500                 const char *device)
5501 {
5502   struct guestfs_blockdev_getss_args args;
5503   struct blockdev_getss_ctx ctx;
5504   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5505   int serial;
5506
5507   if (check_state (g, "guestfs_blockdev_getss") == -1) return -1;
5508
5509   memset (&ctx, 0, sizeof ctx);
5510
5511   args.device = (char *) device;
5512   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_GETSS,
5513         (xdrproc_t) xdr_guestfs_blockdev_getss_args, (char *) &args);
5514   if (serial == -1)
5515     return -1;
5516
5517   ctx.cb_sequence = 0;
5518   guestfs_set_send_callback (g, blockdev_getss_send_cb, &ctx);
5519   (void) ml->main_loop_run (ml, g);
5520   guestfs_set_send_callback (g, NULL, NULL);
5521   if (ctx.cb_sequence != 1) {
5522     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_getss");
5523     return -1;
5524   }
5525
5526   guestfs__switch_to_receiving (g);
5527   ctx.cb_sequence = 0;
5528   guestfs_set_reply_callback (g, blockdev_getss_reply_cb, &ctx);
5529   (void) ml->main_loop_run (ml, g);
5530   guestfs_set_reply_callback (g, NULL, NULL);
5531   if (ctx.cb_sequence != 1001) {
5532     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss");
5533     return -1;
5534   }
5535
5536   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1)
5537     return -1;
5538
5539   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5540     error (g, "%s", ctx.err.error_message);
5541     return -1;
5542   }
5543
5544   return ctx.ret.sectorsize;
5545 }
5546
5547 struct blockdev_getbsz_ctx {
5548   /* This flag is set by the callbacks, so we know we've done
5549    * the callbacks as expected, and in the right sequence.
5550    * 0 = not called, 1 = send called,
5551    * 1001 = reply called.
5552    */
5553   int cb_sequence;
5554   struct guestfs_message_header hdr;
5555   struct guestfs_message_error err;
5556   struct guestfs_blockdev_getbsz_ret ret;
5557 };
5558
5559 static void blockdev_getbsz_send_cb (guestfs_h *g, void *data)
5560 {
5561   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5562   struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data;
5563
5564   ctx->cb_sequence = 1;
5565   ml->main_loop_quit (ml, g);
5566 }
5567
5568 static void blockdev_getbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5569 {
5570   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5571   struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data;
5572
5573   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5574     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz");
5575     return;
5576   }
5577   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5578     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5579       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz");
5580       return;
5581     }
5582     goto done;
5583   }
5584   if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &ctx->ret)) {
5585     error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz");
5586     return;
5587   }
5588  done:
5589   ctx->cb_sequence = 1001;
5590   ml->main_loop_quit (ml, g);
5591 }
5592
5593 int guestfs_blockdev_getbsz (guestfs_h *g,
5594                 const char *device)
5595 {
5596   struct guestfs_blockdev_getbsz_args args;
5597   struct blockdev_getbsz_ctx ctx;
5598   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5599   int serial;
5600
5601   if (check_state (g, "guestfs_blockdev_getbsz") == -1) return -1;
5602
5603   memset (&ctx, 0, sizeof ctx);
5604
5605   args.device = (char *) device;
5606   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
5607         (xdrproc_t) xdr_guestfs_blockdev_getbsz_args, (char *) &args);
5608   if (serial == -1)
5609     return -1;
5610
5611   ctx.cb_sequence = 0;
5612   guestfs_set_send_callback (g, blockdev_getbsz_send_cb, &ctx);
5613   (void) ml->main_loop_run (ml, g);
5614   guestfs_set_send_callback (g, NULL, NULL);
5615   if (ctx.cb_sequence != 1) {
5616     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_getbsz");
5617     return -1;
5618   }
5619
5620   guestfs__switch_to_receiving (g);
5621   ctx.cb_sequence = 0;
5622   guestfs_set_reply_callback (g, blockdev_getbsz_reply_cb, &ctx);
5623   (void) ml->main_loop_run (ml, g);
5624   guestfs_set_reply_callback (g, NULL, NULL);
5625   if (ctx.cb_sequence != 1001) {
5626     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz");
5627     return -1;
5628   }
5629
5630   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1)
5631     return -1;
5632
5633   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5634     error (g, "%s", ctx.err.error_message);
5635     return -1;
5636   }
5637
5638   return ctx.ret.blocksize;
5639 }
5640
5641 struct blockdev_setbsz_ctx {
5642   /* This flag is set by the callbacks, so we know we've done
5643    * the callbacks as expected, and in the right sequence.
5644    * 0 = not called, 1 = send called,
5645    * 1001 = reply called.
5646    */
5647   int cb_sequence;
5648   struct guestfs_message_header hdr;
5649   struct guestfs_message_error err;
5650 };
5651
5652 static void blockdev_setbsz_send_cb (guestfs_h *g, void *data)
5653 {
5654   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5655   struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data;
5656
5657   ctx->cb_sequence = 1;
5658   ml->main_loop_quit (ml, g);
5659 }
5660
5661 static void blockdev_setbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5662 {
5663   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5664   struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data;
5665
5666   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5667     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz");
5668     return;
5669   }
5670   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5671     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5672       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz");
5673       return;
5674     }
5675     goto done;
5676   }
5677  done:
5678   ctx->cb_sequence = 1001;
5679   ml->main_loop_quit (ml, g);
5680 }
5681
5682 int guestfs_blockdev_setbsz (guestfs_h *g,
5683                 const char *device,
5684                 int blocksize)
5685 {
5686   struct guestfs_blockdev_setbsz_args args;
5687   struct blockdev_setbsz_ctx ctx;
5688   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5689   int serial;
5690
5691   if (check_state (g, "guestfs_blockdev_setbsz") == -1) return -1;
5692
5693   memset (&ctx, 0, sizeof ctx);
5694
5695   args.device = (char *) device;
5696   args.blocksize = blocksize;
5697   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_SETBSZ,
5698         (xdrproc_t) xdr_guestfs_blockdev_setbsz_args, (char *) &args);
5699   if (serial == -1)
5700     return -1;
5701
5702   ctx.cb_sequence = 0;
5703   guestfs_set_send_callback (g, blockdev_setbsz_send_cb, &ctx);
5704   (void) ml->main_loop_run (ml, g);
5705   guestfs_set_send_callback (g, NULL, NULL);
5706   if (ctx.cb_sequence != 1) {
5707     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_setbsz");
5708     return -1;
5709   }
5710
5711   guestfs__switch_to_receiving (g);
5712   ctx.cb_sequence = 0;
5713   guestfs_set_reply_callback (g, blockdev_setbsz_reply_cb, &ctx);
5714   (void) ml->main_loop_run (ml, g);
5715   guestfs_set_reply_callback (g, NULL, NULL);
5716   if (ctx.cb_sequence != 1001) {
5717     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz");
5718     return -1;
5719   }
5720
5721   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1)
5722     return -1;
5723
5724   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5725     error (g, "%s", ctx.err.error_message);
5726     return -1;
5727   }
5728
5729   return 0;
5730 }
5731
5732 struct blockdev_getsz_ctx {
5733   /* This flag is set by the callbacks, so we know we've done
5734    * the callbacks as expected, and in the right sequence.
5735    * 0 = not called, 1 = send called,
5736    * 1001 = reply called.
5737    */
5738   int cb_sequence;
5739   struct guestfs_message_header hdr;
5740   struct guestfs_message_error err;
5741   struct guestfs_blockdev_getsz_ret ret;
5742 };
5743
5744 static void blockdev_getsz_send_cb (guestfs_h *g, void *data)
5745 {
5746   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5747   struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data;
5748
5749   ctx->cb_sequence = 1;
5750   ml->main_loop_quit (ml, g);
5751 }
5752
5753 static void blockdev_getsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5754 {
5755   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5756   struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data;
5757
5758   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5759     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz");
5760     return;
5761   }
5762   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5763     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5764       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz");
5765       return;
5766     }
5767     goto done;
5768   }
5769   if (!xdr_guestfs_blockdev_getsz_ret (xdr, &ctx->ret)) {
5770     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz");
5771     return;
5772   }
5773  done:
5774   ctx->cb_sequence = 1001;
5775   ml->main_loop_quit (ml, g);
5776 }
5777
5778 int64_t guestfs_blockdev_getsz (guestfs_h *g,
5779                 const char *device)
5780 {
5781   struct guestfs_blockdev_getsz_args args;
5782   struct blockdev_getsz_ctx ctx;
5783   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5784   int serial;
5785
5786   if (check_state (g, "guestfs_blockdev_getsz") == -1) return -1;
5787
5788   memset (&ctx, 0, sizeof ctx);
5789
5790   args.device = (char *) device;
5791   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
5792         (xdrproc_t) xdr_guestfs_blockdev_getsz_args, (char *) &args);
5793   if (serial == -1)
5794     return -1;
5795
5796   ctx.cb_sequence = 0;
5797   guestfs_set_send_callback (g, blockdev_getsz_send_cb, &ctx);
5798   (void) ml->main_loop_run (ml, g);
5799   guestfs_set_send_callback (g, NULL, NULL);
5800   if (ctx.cb_sequence != 1) {
5801     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_getsz");
5802     return -1;
5803   }
5804
5805   guestfs__switch_to_receiving (g);
5806   ctx.cb_sequence = 0;
5807   guestfs_set_reply_callback (g, blockdev_getsz_reply_cb, &ctx);
5808   (void) ml->main_loop_run (ml, g);
5809   guestfs_set_reply_callback (g, NULL, NULL);
5810   if (ctx.cb_sequence != 1001) {
5811     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz");
5812     return -1;
5813   }
5814
5815   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1)
5816     return -1;
5817
5818   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5819     error (g, "%s", ctx.err.error_message);
5820     return -1;
5821   }
5822
5823   return ctx.ret.sizeinsectors;
5824 }
5825
5826 struct blockdev_getsize64_ctx {
5827   /* This flag is set by the callbacks, so we know we've done
5828    * the callbacks as expected, and in the right sequence.
5829    * 0 = not called, 1 = send called,
5830    * 1001 = reply called.
5831    */
5832   int cb_sequence;
5833   struct guestfs_message_header hdr;
5834   struct guestfs_message_error err;
5835   struct guestfs_blockdev_getsize64_ret ret;
5836 };
5837
5838 static void blockdev_getsize64_send_cb (guestfs_h *g, void *data)
5839 {
5840   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5841   struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data;
5842
5843   ctx->cb_sequence = 1;
5844   ml->main_loop_quit (ml, g);
5845 }
5846
5847 static void blockdev_getsize64_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5848 {
5849   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5850   struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data;
5851
5852   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5853     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64");
5854     return;
5855   }
5856   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5857     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5858       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64");
5859       return;
5860     }
5861     goto done;
5862   }
5863   if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &ctx->ret)) {
5864     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64");
5865     return;
5866   }
5867  done:
5868   ctx->cb_sequence = 1001;
5869   ml->main_loop_quit (ml, g);
5870 }
5871
5872 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
5873                 const char *device)
5874 {
5875   struct guestfs_blockdev_getsize64_args args;
5876   struct blockdev_getsize64_ctx ctx;
5877   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5878   int serial;
5879
5880   if (check_state (g, "guestfs_blockdev_getsize64") == -1) return -1;
5881
5882   memset (&ctx, 0, sizeof ctx);
5883
5884   args.device = (char *) device;
5885   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
5886         (xdrproc_t) xdr_guestfs_blockdev_getsize64_args, (char *) &args);
5887   if (serial == -1)
5888     return -1;
5889
5890   ctx.cb_sequence = 0;
5891   guestfs_set_send_callback (g, blockdev_getsize64_send_cb, &ctx);
5892   (void) ml->main_loop_run (ml, g);
5893   guestfs_set_send_callback (g, NULL, NULL);
5894   if (ctx.cb_sequence != 1) {
5895     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_getsize64");
5896     return -1;
5897   }
5898
5899   guestfs__switch_to_receiving (g);
5900   ctx.cb_sequence = 0;
5901   guestfs_set_reply_callback (g, blockdev_getsize64_reply_cb, &ctx);
5902   (void) ml->main_loop_run (ml, g);
5903   guestfs_set_reply_callback (g, NULL, NULL);
5904   if (ctx.cb_sequence != 1001) {
5905     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64");
5906     return -1;
5907   }
5908
5909   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1)
5910     return -1;
5911
5912   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5913     error (g, "%s", ctx.err.error_message);
5914     return -1;
5915   }
5916
5917   return ctx.ret.sizeinbytes;
5918 }
5919
5920 struct blockdev_flushbufs_ctx {
5921   /* This flag is set by the callbacks, so we know we've done
5922    * the callbacks as expected, and in the right sequence.
5923    * 0 = not called, 1 = send called,
5924    * 1001 = reply called.
5925    */
5926   int cb_sequence;
5927   struct guestfs_message_header hdr;
5928   struct guestfs_message_error err;
5929 };
5930
5931 static void blockdev_flushbufs_send_cb (guestfs_h *g, void *data)
5932 {
5933   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5934   struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data;
5935
5936   ctx->cb_sequence = 1;
5937   ml->main_loop_quit (ml, g);
5938 }
5939
5940 static void blockdev_flushbufs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5941 {
5942   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5943   struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data;
5944
5945   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5946     error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs");
5947     return;
5948   }
5949   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5950     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5951       error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs");
5952       return;
5953     }
5954     goto done;
5955   }
5956  done:
5957   ctx->cb_sequence = 1001;
5958   ml->main_loop_quit (ml, g);
5959 }
5960
5961 int guestfs_blockdev_flushbufs (guestfs_h *g,
5962                 const char *device)
5963 {
5964   struct guestfs_blockdev_flushbufs_args args;
5965   struct blockdev_flushbufs_ctx ctx;
5966   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5967   int serial;
5968
5969   if (check_state (g, "guestfs_blockdev_flushbufs") == -1) return -1;
5970
5971   memset (&ctx, 0, sizeof ctx);
5972
5973   args.device = (char *) device;
5974   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
5975         (xdrproc_t) xdr_guestfs_blockdev_flushbufs_args, (char *) &args);
5976   if (serial == -1)
5977     return -1;
5978
5979   ctx.cb_sequence = 0;
5980   guestfs_set_send_callback (g, blockdev_flushbufs_send_cb, &ctx);
5981   (void) ml->main_loop_run (ml, g);
5982   guestfs_set_send_callback (g, NULL, NULL);
5983   if (ctx.cb_sequence != 1) {
5984     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_flushbufs");
5985     return -1;
5986   }
5987
5988   guestfs__switch_to_receiving (g);
5989   ctx.cb_sequence = 0;
5990   guestfs_set_reply_callback (g, blockdev_flushbufs_reply_cb, &ctx);
5991   (void) ml->main_loop_run (ml, g);
5992   guestfs_set_reply_callback (g, NULL, NULL);
5993   if (ctx.cb_sequence != 1001) {
5994     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs");
5995     return -1;
5996   }
5997
5998   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1)
5999     return -1;
6000
6001   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6002     error (g, "%s", ctx.err.error_message);
6003     return -1;
6004   }
6005
6006   return 0;
6007 }
6008
6009 struct blockdev_rereadpt_ctx {
6010   /* This flag is set by the callbacks, so we know we've done
6011    * the callbacks as expected, and in the right sequence.
6012    * 0 = not called, 1 = send called,
6013    * 1001 = reply called.
6014    */
6015   int cb_sequence;
6016   struct guestfs_message_header hdr;
6017   struct guestfs_message_error err;
6018 };
6019
6020 static void blockdev_rereadpt_send_cb (guestfs_h *g, void *data)
6021 {
6022   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6023   struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data;
6024
6025   ctx->cb_sequence = 1;
6026   ml->main_loop_quit (ml, g);
6027 }
6028
6029 static void blockdev_rereadpt_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6030 {
6031   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6032   struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data;
6033
6034   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6035     error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt");
6036     return;
6037   }
6038   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6039     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6040       error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt");
6041       return;
6042     }
6043     goto done;
6044   }
6045  done:
6046   ctx->cb_sequence = 1001;
6047   ml->main_loop_quit (ml, g);
6048 }
6049
6050 int guestfs_blockdev_rereadpt (guestfs_h *g,
6051                 const char *device)
6052 {
6053   struct guestfs_blockdev_rereadpt_args args;
6054   struct blockdev_rereadpt_ctx ctx;
6055   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6056   int serial;
6057
6058   if (check_state (g, "guestfs_blockdev_rereadpt") == -1) return -1;
6059
6060   memset (&ctx, 0, sizeof ctx);
6061
6062   args.device = (char *) device;
6063   serial = guestfs__send (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
6064         (xdrproc_t) xdr_guestfs_blockdev_rereadpt_args, (char *) &args);
6065   if (serial == -1)
6066     return -1;
6067
6068   ctx.cb_sequence = 0;
6069   guestfs_set_send_callback (g, blockdev_rereadpt_send_cb, &ctx);
6070   (void) ml->main_loop_run (ml, g);
6071   guestfs_set_send_callback (g, NULL, NULL);
6072   if (ctx.cb_sequence != 1) {
6073     error (g, "%s send failed, see earlier error messages", "guestfs_blockdev_rereadpt");
6074     return -1;
6075   }
6076
6077   guestfs__switch_to_receiving (g);
6078   ctx.cb_sequence = 0;
6079   guestfs_set_reply_callback (g, blockdev_rereadpt_reply_cb, &ctx);
6080   (void) ml->main_loop_run (ml, g);
6081   guestfs_set_reply_callback (g, NULL, NULL);
6082   if (ctx.cb_sequence != 1001) {
6083     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt");
6084     return -1;
6085   }
6086
6087   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1)
6088     return -1;
6089
6090   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6091     error (g, "%s", ctx.err.error_message);
6092     return -1;
6093   }
6094
6095   return 0;
6096 }
6097
6098 struct upload_ctx {
6099   /* This flag is set by the callbacks, so we know we've done
6100    * the callbacks as expected, and in the right sequence.
6101    * 0 = not called, 1 = send called,
6102    * 1001 = reply called.
6103    */
6104   int cb_sequence;
6105   struct guestfs_message_header hdr;
6106   struct guestfs_message_error err;
6107 };
6108
6109 static void upload_send_cb (guestfs_h *g, void *data)
6110 {
6111   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6112   struct upload_ctx *ctx = (struct upload_ctx *) data;
6113
6114   ctx->cb_sequence = 1;
6115   ml->main_loop_quit (ml, g);
6116 }
6117
6118 static void upload_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6119 {
6120   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6121   struct upload_ctx *ctx = (struct upload_ctx *) data;
6122
6123   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6124     error (g, "%s: failed to parse reply header", "guestfs_upload");
6125     return;
6126   }
6127   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6128     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6129       error (g, "%s: failed to parse reply error", "guestfs_upload");
6130       return;
6131     }
6132     goto done;
6133   }
6134  done:
6135   ctx->cb_sequence = 1001;
6136   ml->main_loop_quit (ml, g);
6137 }
6138
6139 int guestfs_upload (guestfs_h *g,
6140                 const char *filename,
6141                 const char *remotefilename)
6142 {
6143   struct guestfs_upload_args args;
6144   struct upload_ctx ctx;
6145   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6146   int serial;
6147
6148   if (check_state (g, "guestfs_upload") == -1) return -1;
6149
6150   memset (&ctx, 0, sizeof ctx);
6151
6152   args.remotefilename = (char *) remotefilename;
6153   serial = guestfs__send (g, GUESTFS_PROC_UPLOAD,
6154         (xdrproc_t) xdr_guestfs_upload_args, (char *) &args);
6155   if (serial == -1)
6156     return -1;
6157
6158   ctx.cb_sequence = 0;
6159   guestfs_set_send_callback (g, upload_send_cb, &ctx);
6160   (void) ml->main_loop_run (ml, g);
6161   guestfs_set_send_callback (g, NULL, NULL);
6162   if (ctx.cb_sequence != 1) {
6163     error (g, "%s send failed, see earlier error messages", "guestfs_upload");
6164     return -1;
6165   }
6166
6167   if (guestfs__send_file_sync (ml, g, filename) == -1)
6168     return -1;
6169
6170   guestfs__switch_to_receiving (g);
6171   ctx.cb_sequence = 0;
6172   guestfs_set_reply_callback (g, upload_reply_cb, &ctx);
6173   (void) ml->main_loop_run (ml, g);
6174   guestfs_set_reply_callback (g, NULL, NULL);
6175   if (ctx.cb_sequence != 1001) {
6176     error (g, "%s reply failed, see earlier error messages", "guestfs_upload");
6177     return -1;
6178   }
6179
6180   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UPLOAD, serial) == -1)
6181     return -1;
6182
6183   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6184     error (g, "%s", ctx.err.error_message);
6185     return -1;
6186   }
6187
6188   return 0;
6189 }
6190
6191 struct download_ctx {
6192   /* This flag is set by the callbacks, so we know we've done
6193    * the callbacks as expected, and in the right sequence.
6194    * 0 = not called, 1 = send called,
6195    * 1001 = reply called.
6196    */
6197   int cb_sequence;
6198   struct guestfs_message_header hdr;
6199   struct guestfs_message_error err;
6200 };
6201
6202 static void download_send_cb (guestfs_h *g, void *data)
6203 {
6204   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6205   struct download_ctx *ctx = (struct download_ctx *) data;
6206
6207   ctx->cb_sequence = 1;
6208   ml->main_loop_quit (ml, g);
6209 }
6210
6211 static void download_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6212 {
6213   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6214   struct download_ctx *ctx = (struct download_ctx *) data;
6215
6216   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6217     error (g, "%s: failed to parse reply header", "guestfs_download");
6218     return;
6219   }
6220   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6221     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6222       error (g, "%s: failed to parse reply error", "guestfs_download");
6223       return;
6224     }
6225     goto done;
6226   }
6227  done:
6228   ctx->cb_sequence = 1001;
6229   ml->main_loop_quit (ml, g);
6230 }
6231
6232 int guestfs_download (guestfs_h *g,
6233                 const char *remotefilename,
6234                 const char *filename)
6235 {
6236   struct guestfs_download_args args;
6237   struct download_ctx ctx;
6238   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6239   int serial;
6240
6241   if (check_state (g, "guestfs_download") == -1) return -1;
6242
6243   memset (&ctx, 0, sizeof ctx);
6244
6245   args.remotefilename = (char *) remotefilename;
6246   serial = guestfs__send (g, GUESTFS_PROC_DOWNLOAD,
6247         (xdrproc_t) xdr_guestfs_download_args, (char *) &args);
6248   if (serial == -1)
6249     return -1;
6250
6251   ctx.cb_sequence = 0;
6252   guestfs_set_send_callback (g, download_send_cb, &ctx);
6253   (void) ml->main_loop_run (ml, g);
6254   guestfs_set_send_callback (g, NULL, NULL);
6255   if (ctx.cb_sequence != 1) {
6256     error (g, "%s send failed, see earlier error messages", "guestfs_download");
6257     return -1;
6258   }
6259
6260   guestfs__switch_to_receiving (g);
6261   ctx.cb_sequence = 0;
6262   guestfs_set_reply_callback (g, download_reply_cb, &ctx);
6263   (void) ml->main_loop_run (ml, g);
6264   guestfs_set_reply_callback (g, NULL, NULL);
6265   if (ctx.cb_sequence != 1001) {
6266     error (g, "%s reply failed, see earlier error messages", "guestfs_download");
6267     return -1;
6268   }
6269
6270   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1)
6271     return -1;
6272
6273   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6274     error (g, "%s", ctx.err.error_message);
6275     return -1;
6276   }
6277
6278   if (guestfs__receive_file_sync (ml, g, filename) == -1)
6279     return -1;
6280
6281   return 0;
6282 }
6283