Generated code for drop-caches command.
[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 = reply_cb called.
90    */
91   int cb_sequence;
92   struct guestfs_message_header hdr;
93   struct guestfs_message_error err;
94 };
95
96 static void mount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
97 {
98   guestfs_main_loop *ml = guestfs_get_main_loop (g);
99   struct mount_ctx *ctx = (struct mount_ctx *) data;
100
101   /* This should definitely not happen. */
102   if (ctx->cb_sequence != 0) {
103     ctx->cb_sequence = 9999;
104     error (g, "%s: internal error: reply callback called twice", "guestfs_mount");
105     return;
106   }
107
108   ml->main_loop_quit (ml, g);
109
110   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
111     error (g, "%s: failed to parse reply header", "guestfs_mount");
112     return;
113   }
114   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
115     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
116       error (g, "%s: failed to parse reply error", "guestfs_mount");
117       return;
118     }
119     goto done;
120   }
121  done:
122   ctx->cb_sequence = 1;
123 }
124
125 int guestfs_mount (guestfs_h *g,
126                 const char *device,
127                 const char *mountpoint)
128 {
129   struct guestfs_mount_args args;
130   struct mount_ctx ctx;
131   guestfs_main_loop *ml = guestfs_get_main_loop (g);
132   int serial;
133
134   if (check_state (g, "guestfs_mount") == -1) return -1;
135   guestfs_set_busy (g);
136
137   memset (&ctx, 0, sizeof ctx);
138
139   args.device = (char *) device;
140   args.mountpoint = (char *) mountpoint;
141   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT,
142         (xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
143   if (serial == -1) {
144     guestfs_set_ready (g);
145     return -1;
146   }
147
148   guestfs__switch_to_receiving (g);
149   ctx.cb_sequence = 0;
150   guestfs_set_reply_callback (g, mount_reply_cb, &ctx);
151   (void) ml->main_loop_run (ml, g);
152   guestfs_set_reply_callback (g, NULL, NULL);
153   if (ctx.cb_sequence != 1) {
154     error (g, "%s reply failed, see earlier error messages", "guestfs_mount");
155     guestfs_set_ready (g);
156     return -1;
157   }
158
159   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT, serial) == -1) {
160     guestfs_set_ready (g);
161     return -1;
162   }
163
164   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
165     error (g, "%s", ctx.err.error_message);
166     guestfs_set_ready (g);
167     return -1;
168   }
169
170   guestfs_set_ready (g);
171   return 0;
172 }
173
174 struct sync_ctx {
175   /* This flag is set by the callbacks, so we know we've done
176    * the callbacks as expected, and in the right sequence.
177    * 0 = not called, 1 = reply_cb called.
178    */
179   int cb_sequence;
180   struct guestfs_message_header hdr;
181   struct guestfs_message_error err;
182 };
183
184 static void sync_reply_cb (guestfs_h *g, void *data, XDR *xdr)
185 {
186   guestfs_main_loop *ml = guestfs_get_main_loop (g);
187   struct sync_ctx *ctx = (struct sync_ctx *) data;
188
189   /* This should definitely not happen. */
190   if (ctx->cb_sequence != 0) {
191     ctx->cb_sequence = 9999;
192     error (g, "%s: internal error: reply callback called twice", "guestfs_sync");
193     return;
194   }
195
196   ml->main_loop_quit (ml, g);
197
198   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
199     error (g, "%s: failed to parse reply header", "guestfs_sync");
200     return;
201   }
202   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
203     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
204       error (g, "%s: failed to parse reply error", "guestfs_sync");
205       return;
206     }
207     goto done;
208   }
209  done:
210   ctx->cb_sequence = 1;
211 }
212
213 int guestfs_sync (guestfs_h *g)
214 {
215   struct sync_ctx ctx;
216   guestfs_main_loop *ml = guestfs_get_main_loop (g);
217   int serial;
218
219   if (check_state (g, "guestfs_sync") == -1) return -1;
220   guestfs_set_busy (g);
221
222   memset (&ctx, 0, sizeof ctx);
223
224   serial = guestfs__send_sync (g, GUESTFS_PROC_SYNC, NULL, NULL);
225   if (serial == -1) {
226     guestfs_set_ready (g);
227     return -1;
228   }
229
230   guestfs__switch_to_receiving (g);
231   ctx.cb_sequence = 0;
232   guestfs_set_reply_callback (g, sync_reply_cb, &ctx);
233   (void) ml->main_loop_run (ml, g);
234   guestfs_set_reply_callback (g, NULL, NULL);
235   if (ctx.cb_sequence != 1) {
236     error (g, "%s reply failed, see earlier error messages", "guestfs_sync");
237     guestfs_set_ready (g);
238     return -1;
239   }
240
241   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SYNC, serial) == -1) {
242     guestfs_set_ready (g);
243     return -1;
244   }
245
246   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
247     error (g, "%s", ctx.err.error_message);
248     guestfs_set_ready (g);
249     return -1;
250   }
251
252   guestfs_set_ready (g);
253   return 0;
254 }
255
256 struct touch_ctx {
257   /* This flag is set by the callbacks, so we know we've done
258    * the callbacks as expected, and in the right sequence.
259    * 0 = not called, 1 = reply_cb called.
260    */
261   int cb_sequence;
262   struct guestfs_message_header hdr;
263   struct guestfs_message_error err;
264 };
265
266 static void touch_reply_cb (guestfs_h *g, void *data, XDR *xdr)
267 {
268   guestfs_main_loop *ml = guestfs_get_main_loop (g);
269   struct touch_ctx *ctx = (struct touch_ctx *) data;
270
271   /* This should definitely not happen. */
272   if (ctx->cb_sequence != 0) {
273     ctx->cb_sequence = 9999;
274     error (g, "%s: internal error: reply callback called twice", "guestfs_touch");
275     return;
276   }
277
278   ml->main_loop_quit (ml, g);
279
280   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
281     error (g, "%s: failed to parse reply header", "guestfs_touch");
282     return;
283   }
284   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
285     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
286       error (g, "%s: failed to parse reply error", "guestfs_touch");
287       return;
288     }
289     goto done;
290   }
291  done:
292   ctx->cb_sequence = 1;
293 }
294
295 int guestfs_touch (guestfs_h *g,
296                 const char *path)
297 {
298   struct guestfs_touch_args args;
299   struct touch_ctx ctx;
300   guestfs_main_loop *ml = guestfs_get_main_loop (g);
301   int serial;
302
303   if (check_state (g, "guestfs_touch") == -1) return -1;
304   guestfs_set_busy (g);
305
306   memset (&ctx, 0, sizeof ctx);
307
308   args.path = (char *) path;
309   serial = guestfs__send_sync (g, GUESTFS_PROC_TOUCH,
310         (xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
311   if (serial == -1) {
312     guestfs_set_ready (g);
313     return -1;
314   }
315
316   guestfs__switch_to_receiving (g);
317   ctx.cb_sequence = 0;
318   guestfs_set_reply_callback (g, touch_reply_cb, &ctx);
319   (void) ml->main_loop_run (ml, g);
320   guestfs_set_reply_callback (g, NULL, NULL);
321   if (ctx.cb_sequence != 1) {
322     error (g, "%s reply failed, see earlier error messages", "guestfs_touch");
323     guestfs_set_ready (g);
324     return -1;
325   }
326
327   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TOUCH, serial) == -1) {
328     guestfs_set_ready (g);
329     return -1;
330   }
331
332   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
333     error (g, "%s", ctx.err.error_message);
334     guestfs_set_ready (g);
335     return -1;
336   }
337
338   guestfs_set_ready (g);
339   return 0;
340 }
341
342 struct cat_ctx {
343   /* This flag is set by the callbacks, so we know we've done
344    * the callbacks as expected, and in the right sequence.
345    * 0 = not called, 1 = reply_cb called.
346    */
347   int cb_sequence;
348   struct guestfs_message_header hdr;
349   struct guestfs_message_error err;
350   struct guestfs_cat_ret ret;
351 };
352
353 static void cat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
354 {
355   guestfs_main_loop *ml = guestfs_get_main_loop (g);
356   struct cat_ctx *ctx = (struct cat_ctx *) data;
357
358   /* This should definitely not happen. */
359   if (ctx->cb_sequence != 0) {
360     ctx->cb_sequence = 9999;
361     error (g, "%s: internal error: reply callback called twice", "guestfs_cat");
362     return;
363   }
364
365   ml->main_loop_quit (ml, g);
366
367   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
368     error (g, "%s: failed to parse reply header", "guestfs_cat");
369     return;
370   }
371   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
372     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
373       error (g, "%s: failed to parse reply error", "guestfs_cat");
374       return;
375     }
376     goto done;
377   }
378   if (!xdr_guestfs_cat_ret (xdr, &ctx->ret)) {
379     error (g, "%s: failed to parse reply", "guestfs_cat");
380     return;
381   }
382  done:
383   ctx->cb_sequence = 1;
384 }
385
386 char *guestfs_cat (guestfs_h *g,
387                 const char *path)
388 {
389   struct guestfs_cat_args args;
390   struct cat_ctx ctx;
391   guestfs_main_loop *ml = guestfs_get_main_loop (g);
392   int serial;
393
394   if (check_state (g, "guestfs_cat") == -1) return NULL;
395   guestfs_set_busy (g);
396
397   memset (&ctx, 0, sizeof ctx);
398
399   args.path = (char *) path;
400   serial = guestfs__send_sync (g, GUESTFS_PROC_CAT,
401         (xdrproc_t) xdr_guestfs_cat_args, (char *) &args);
402   if (serial == -1) {
403     guestfs_set_ready (g);
404     return NULL;
405   }
406
407   guestfs__switch_to_receiving (g);
408   ctx.cb_sequence = 0;
409   guestfs_set_reply_callback (g, cat_reply_cb, &ctx);
410   (void) ml->main_loop_run (ml, g);
411   guestfs_set_reply_callback (g, NULL, NULL);
412   if (ctx.cb_sequence != 1) {
413     error (g, "%s reply failed, see earlier error messages", "guestfs_cat");
414     guestfs_set_ready (g);
415     return NULL;
416   }
417
418   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CAT, serial) == -1) {
419     guestfs_set_ready (g);
420     return NULL;
421   }
422
423   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
424     error (g, "%s", ctx.err.error_message);
425     guestfs_set_ready (g);
426     return NULL;
427   }
428
429   guestfs_set_ready (g);
430   return ctx.ret.content; /* caller will free */
431 }
432
433 struct ll_ctx {
434   /* This flag is set by the callbacks, so we know we've done
435    * the callbacks as expected, and in the right sequence.
436    * 0 = not called, 1 = reply_cb called.
437    */
438   int cb_sequence;
439   struct guestfs_message_header hdr;
440   struct guestfs_message_error err;
441   struct guestfs_ll_ret ret;
442 };
443
444 static void ll_reply_cb (guestfs_h *g, void *data, XDR *xdr)
445 {
446   guestfs_main_loop *ml = guestfs_get_main_loop (g);
447   struct ll_ctx *ctx = (struct ll_ctx *) data;
448
449   /* This should definitely not happen. */
450   if (ctx->cb_sequence != 0) {
451     ctx->cb_sequence = 9999;
452     error (g, "%s: internal error: reply callback called twice", "guestfs_ll");
453     return;
454   }
455
456   ml->main_loop_quit (ml, g);
457
458   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
459     error (g, "%s: failed to parse reply header", "guestfs_ll");
460     return;
461   }
462   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
463     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
464       error (g, "%s: failed to parse reply error", "guestfs_ll");
465       return;
466     }
467     goto done;
468   }
469   if (!xdr_guestfs_ll_ret (xdr, &ctx->ret)) {
470     error (g, "%s: failed to parse reply", "guestfs_ll");
471     return;
472   }
473  done:
474   ctx->cb_sequence = 1;
475 }
476
477 char *guestfs_ll (guestfs_h *g,
478                 const char *directory)
479 {
480   struct guestfs_ll_args args;
481   struct ll_ctx ctx;
482   guestfs_main_loop *ml = guestfs_get_main_loop (g);
483   int serial;
484
485   if (check_state (g, "guestfs_ll") == -1) return NULL;
486   guestfs_set_busy (g);
487
488   memset (&ctx, 0, sizeof ctx);
489
490   args.directory = (char *) directory;
491   serial = guestfs__send_sync (g, GUESTFS_PROC_LL,
492         (xdrproc_t) xdr_guestfs_ll_args, (char *) &args);
493   if (serial == -1) {
494     guestfs_set_ready (g);
495     return NULL;
496   }
497
498   guestfs__switch_to_receiving (g);
499   ctx.cb_sequence = 0;
500   guestfs_set_reply_callback (g, ll_reply_cb, &ctx);
501   (void) ml->main_loop_run (ml, g);
502   guestfs_set_reply_callback (g, NULL, NULL);
503   if (ctx.cb_sequence != 1) {
504     error (g, "%s reply failed, see earlier error messages", "guestfs_ll");
505     guestfs_set_ready (g);
506     return NULL;
507   }
508
509   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LL, serial) == -1) {
510     guestfs_set_ready (g);
511     return NULL;
512   }
513
514   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
515     error (g, "%s", ctx.err.error_message);
516     guestfs_set_ready (g);
517     return NULL;
518   }
519
520   guestfs_set_ready (g);
521   return ctx.ret.listing; /* caller will free */
522 }
523
524 struct ls_ctx {
525   /* This flag is set by the callbacks, so we know we've done
526    * the callbacks as expected, and in the right sequence.
527    * 0 = not called, 1 = reply_cb called.
528    */
529   int cb_sequence;
530   struct guestfs_message_header hdr;
531   struct guestfs_message_error err;
532   struct guestfs_ls_ret ret;
533 };
534
535 static void ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
536 {
537   guestfs_main_loop *ml = guestfs_get_main_loop (g);
538   struct ls_ctx *ctx = (struct ls_ctx *) data;
539
540   /* This should definitely not happen. */
541   if (ctx->cb_sequence != 0) {
542     ctx->cb_sequence = 9999;
543     error (g, "%s: internal error: reply callback called twice", "guestfs_ls");
544     return;
545   }
546
547   ml->main_loop_quit (ml, g);
548
549   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
550     error (g, "%s: failed to parse reply header", "guestfs_ls");
551     return;
552   }
553   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
554     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
555       error (g, "%s: failed to parse reply error", "guestfs_ls");
556       return;
557     }
558     goto done;
559   }
560   if (!xdr_guestfs_ls_ret (xdr, &ctx->ret)) {
561     error (g, "%s: failed to parse reply", "guestfs_ls");
562     return;
563   }
564  done:
565   ctx->cb_sequence = 1;
566 }
567
568 char **guestfs_ls (guestfs_h *g,
569                 const char *directory)
570 {
571   struct guestfs_ls_args args;
572   struct ls_ctx ctx;
573   guestfs_main_loop *ml = guestfs_get_main_loop (g);
574   int serial;
575
576   if (check_state (g, "guestfs_ls") == -1) return NULL;
577   guestfs_set_busy (g);
578
579   memset (&ctx, 0, sizeof ctx);
580
581   args.directory = (char *) directory;
582   serial = guestfs__send_sync (g, GUESTFS_PROC_LS,
583         (xdrproc_t) xdr_guestfs_ls_args, (char *) &args);
584   if (serial == -1) {
585     guestfs_set_ready (g);
586     return NULL;
587   }
588
589   guestfs__switch_to_receiving (g);
590   ctx.cb_sequence = 0;
591   guestfs_set_reply_callback (g, ls_reply_cb, &ctx);
592   (void) ml->main_loop_run (ml, g);
593   guestfs_set_reply_callback (g, NULL, NULL);
594   if (ctx.cb_sequence != 1) {
595     error (g, "%s reply failed, see earlier error messages", "guestfs_ls");
596     guestfs_set_ready (g);
597     return NULL;
598   }
599
600   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LS, serial) == -1) {
601     guestfs_set_ready (g);
602     return NULL;
603   }
604
605   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
606     error (g, "%s", ctx.err.error_message);
607     guestfs_set_ready (g);
608     return NULL;
609   }
610
611   guestfs_set_ready (g);
612   /* caller will free this, but we need to add a NULL entry */
613   ctx.ret.listing.listing_val =
614     safe_realloc (g, ctx.ret.listing.listing_val,
615                   sizeof (char *) * (ctx.ret.listing.listing_len + 1));
616   ctx.ret.listing.listing_val[ctx.ret.listing.listing_len] = NULL;
617   return ctx.ret.listing.listing_val;
618 }
619
620 struct list_devices_ctx {
621   /* This flag is set by the callbacks, so we know we've done
622    * the callbacks as expected, and in the right sequence.
623    * 0 = not called, 1 = reply_cb called.
624    */
625   int cb_sequence;
626   struct guestfs_message_header hdr;
627   struct guestfs_message_error err;
628   struct guestfs_list_devices_ret ret;
629 };
630
631 static void list_devices_reply_cb (guestfs_h *g, void *data, XDR *xdr)
632 {
633   guestfs_main_loop *ml = guestfs_get_main_loop (g);
634   struct list_devices_ctx *ctx = (struct list_devices_ctx *) data;
635
636   /* This should definitely not happen. */
637   if (ctx->cb_sequence != 0) {
638     ctx->cb_sequence = 9999;
639     error (g, "%s: internal error: reply callback called twice", "guestfs_list_devices");
640     return;
641   }
642
643   ml->main_loop_quit (ml, g);
644
645   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
646     error (g, "%s: failed to parse reply header", "guestfs_list_devices");
647     return;
648   }
649   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
650     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
651       error (g, "%s: failed to parse reply error", "guestfs_list_devices");
652       return;
653     }
654     goto done;
655   }
656   if (!xdr_guestfs_list_devices_ret (xdr, &ctx->ret)) {
657     error (g, "%s: failed to parse reply", "guestfs_list_devices");
658     return;
659   }
660  done:
661   ctx->cb_sequence = 1;
662 }
663
664 char **guestfs_list_devices (guestfs_h *g)
665 {
666   struct list_devices_ctx ctx;
667   guestfs_main_loop *ml = guestfs_get_main_loop (g);
668   int serial;
669
670   if (check_state (g, "guestfs_list_devices") == -1) return NULL;
671   guestfs_set_busy (g);
672
673   memset (&ctx, 0, sizeof ctx);
674
675   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
676   if (serial == -1) {
677     guestfs_set_ready (g);
678     return NULL;
679   }
680
681   guestfs__switch_to_receiving (g);
682   ctx.cb_sequence = 0;
683   guestfs_set_reply_callback (g, list_devices_reply_cb, &ctx);
684   (void) ml->main_loop_run (ml, g);
685   guestfs_set_reply_callback (g, NULL, NULL);
686   if (ctx.cb_sequence != 1) {
687     error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices");
688     guestfs_set_ready (g);
689     return NULL;
690   }
691
692   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1) {
693     guestfs_set_ready (g);
694     return NULL;
695   }
696
697   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
698     error (g, "%s", ctx.err.error_message);
699     guestfs_set_ready (g);
700     return NULL;
701   }
702
703   guestfs_set_ready (g);
704   /* caller will free this, but we need to add a NULL entry */
705   ctx.ret.devices.devices_val =
706     safe_realloc (g, ctx.ret.devices.devices_val,
707                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
708   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
709   return ctx.ret.devices.devices_val;
710 }
711
712 struct list_partitions_ctx {
713   /* This flag is set by the callbacks, so we know we've done
714    * the callbacks as expected, and in the right sequence.
715    * 0 = not called, 1 = reply_cb called.
716    */
717   int cb_sequence;
718   struct guestfs_message_header hdr;
719   struct guestfs_message_error err;
720   struct guestfs_list_partitions_ret ret;
721 };
722
723 static void list_partitions_reply_cb (guestfs_h *g, void *data, XDR *xdr)
724 {
725   guestfs_main_loop *ml = guestfs_get_main_loop (g);
726   struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data;
727
728   /* This should definitely not happen. */
729   if (ctx->cb_sequence != 0) {
730     ctx->cb_sequence = 9999;
731     error (g, "%s: internal error: reply callback called twice", "guestfs_list_partitions");
732     return;
733   }
734
735   ml->main_loop_quit (ml, g);
736
737   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
738     error (g, "%s: failed to parse reply header", "guestfs_list_partitions");
739     return;
740   }
741   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
742     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
743       error (g, "%s: failed to parse reply error", "guestfs_list_partitions");
744       return;
745     }
746     goto done;
747   }
748   if (!xdr_guestfs_list_partitions_ret (xdr, &ctx->ret)) {
749     error (g, "%s: failed to parse reply", "guestfs_list_partitions");
750     return;
751   }
752  done:
753   ctx->cb_sequence = 1;
754 }
755
756 char **guestfs_list_partitions (guestfs_h *g)
757 {
758   struct list_partitions_ctx ctx;
759   guestfs_main_loop *ml = guestfs_get_main_loop (g);
760   int serial;
761
762   if (check_state (g, "guestfs_list_partitions") == -1) return NULL;
763   guestfs_set_busy (g);
764
765   memset (&ctx, 0, sizeof ctx);
766
767   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
768   if (serial == -1) {
769     guestfs_set_ready (g);
770     return NULL;
771   }
772
773   guestfs__switch_to_receiving (g);
774   ctx.cb_sequence = 0;
775   guestfs_set_reply_callback (g, list_partitions_reply_cb, &ctx);
776   (void) ml->main_loop_run (ml, g);
777   guestfs_set_reply_callback (g, NULL, NULL);
778   if (ctx.cb_sequence != 1) {
779     error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions");
780     guestfs_set_ready (g);
781     return NULL;
782   }
783
784   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1) {
785     guestfs_set_ready (g);
786     return NULL;
787   }
788
789   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
790     error (g, "%s", ctx.err.error_message);
791     guestfs_set_ready (g);
792     return NULL;
793   }
794
795   guestfs_set_ready (g);
796   /* caller will free this, but we need to add a NULL entry */
797   ctx.ret.partitions.partitions_val =
798     safe_realloc (g, ctx.ret.partitions.partitions_val,
799                   sizeof (char *) * (ctx.ret.partitions.partitions_len + 1));
800   ctx.ret.partitions.partitions_val[ctx.ret.partitions.partitions_len] = NULL;
801   return ctx.ret.partitions.partitions_val;
802 }
803
804 struct pvs_ctx {
805   /* This flag is set by the callbacks, so we know we've done
806    * the callbacks as expected, and in the right sequence.
807    * 0 = not called, 1 = reply_cb called.
808    */
809   int cb_sequence;
810   struct guestfs_message_header hdr;
811   struct guestfs_message_error err;
812   struct guestfs_pvs_ret ret;
813 };
814
815 static void pvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
816 {
817   guestfs_main_loop *ml = guestfs_get_main_loop (g);
818   struct pvs_ctx *ctx = (struct pvs_ctx *) data;
819
820   /* This should definitely not happen. */
821   if (ctx->cb_sequence != 0) {
822     ctx->cb_sequence = 9999;
823     error (g, "%s: internal error: reply callback called twice", "guestfs_pvs");
824     return;
825   }
826
827   ml->main_loop_quit (ml, g);
828
829   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
830     error (g, "%s: failed to parse reply header", "guestfs_pvs");
831     return;
832   }
833   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
834     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
835       error (g, "%s: failed to parse reply error", "guestfs_pvs");
836       return;
837     }
838     goto done;
839   }
840   if (!xdr_guestfs_pvs_ret (xdr, &ctx->ret)) {
841     error (g, "%s: failed to parse reply", "guestfs_pvs");
842     return;
843   }
844  done:
845   ctx->cb_sequence = 1;
846 }
847
848 char **guestfs_pvs (guestfs_h *g)
849 {
850   struct pvs_ctx ctx;
851   guestfs_main_loop *ml = guestfs_get_main_loop (g);
852   int serial;
853
854   if (check_state (g, "guestfs_pvs") == -1) return NULL;
855   guestfs_set_busy (g);
856
857   memset (&ctx, 0, sizeof ctx);
858
859   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS, NULL, NULL);
860   if (serial == -1) {
861     guestfs_set_ready (g);
862     return NULL;
863   }
864
865   guestfs__switch_to_receiving (g);
866   ctx.cb_sequence = 0;
867   guestfs_set_reply_callback (g, pvs_reply_cb, &ctx);
868   (void) ml->main_loop_run (ml, g);
869   guestfs_set_reply_callback (g, NULL, NULL);
870   if (ctx.cb_sequence != 1) {
871     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs");
872     guestfs_set_ready (g);
873     return NULL;
874   }
875
876   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS, serial) == -1) {
877     guestfs_set_ready (g);
878     return NULL;
879   }
880
881   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
882     error (g, "%s", ctx.err.error_message);
883     guestfs_set_ready (g);
884     return NULL;
885   }
886
887   guestfs_set_ready (g);
888   /* caller will free this, but we need to add a NULL entry */
889   ctx.ret.physvols.physvols_val =
890     safe_realloc (g, ctx.ret.physvols.physvols_val,
891                   sizeof (char *) * (ctx.ret.physvols.physvols_len + 1));
892   ctx.ret.physvols.physvols_val[ctx.ret.physvols.physvols_len] = NULL;
893   return ctx.ret.physvols.physvols_val;
894 }
895
896 struct vgs_ctx {
897   /* This flag is set by the callbacks, so we know we've done
898    * the callbacks as expected, and in the right sequence.
899    * 0 = not called, 1 = reply_cb called.
900    */
901   int cb_sequence;
902   struct guestfs_message_header hdr;
903   struct guestfs_message_error err;
904   struct guestfs_vgs_ret ret;
905 };
906
907 static void vgs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
908 {
909   guestfs_main_loop *ml = guestfs_get_main_loop (g);
910   struct vgs_ctx *ctx = (struct vgs_ctx *) data;
911
912   /* This should definitely not happen. */
913   if (ctx->cb_sequence != 0) {
914     ctx->cb_sequence = 9999;
915     error (g, "%s: internal error: reply callback called twice", "guestfs_vgs");
916     return;
917   }
918
919   ml->main_loop_quit (ml, g);
920
921   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
922     error (g, "%s: failed to parse reply header", "guestfs_vgs");
923     return;
924   }
925   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
926     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
927       error (g, "%s: failed to parse reply error", "guestfs_vgs");
928       return;
929     }
930     goto done;
931   }
932   if (!xdr_guestfs_vgs_ret (xdr, &ctx->ret)) {
933     error (g, "%s: failed to parse reply", "guestfs_vgs");
934     return;
935   }
936  done:
937   ctx->cb_sequence = 1;
938 }
939
940 char **guestfs_vgs (guestfs_h *g)
941 {
942   struct vgs_ctx ctx;
943   guestfs_main_loop *ml = guestfs_get_main_loop (g);
944   int serial;
945
946   if (check_state (g, "guestfs_vgs") == -1) return NULL;
947   guestfs_set_busy (g);
948
949   memset (&ctx, 0, sizeof ctx);
950
951   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS, NULL, NULL);
952   if (serial == -1) {
953     guestfs_set_ready (g);
954     return NULL;
955   }
956
957   guestfs__switch_to_receiving (g);
958   ctx.cb_sequence = 0;
959   guestfs_set_reply_callback (g, vgs_reply_cb, &ctx);
960   (void) ml->main_loop_run (ml, g);
961   guestfs_set_reply_callback (g, NULL, NULL);
962   if (ctx.cb_sequence != 1) {
963     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs");
964     guestfs_set_ready (g);
965     return NULL;
966   }
967
968   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS, serial) == -1) {
969     guestfs_set_ready (g);
970     return NULL;
971   }
972
973   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
974     error (g, "%s", ctx.err.error_message);
975     guestfs_set_ready (g);
976     return NULL;
977   }
978
979   guestfs_set_ready (g);
980   /* caller will free this, but we need to add a NULL entry */
981   ctx.ret.volgroups.volgroups_val =
982     safe_realloc (g, ctx.ret.volgroups.volgroups_val,
983                   sizeof (char *) * (ctx.ret.volgroups.volgroups_len + 1));
984   ctx.ret.volgroups.volgroups_val[ctx.ret.volgroups.volgroups_len] = NULL;
985   return ctx.ret.volgroups.volgroups_val;
986 }
987
988 struct lvs_ctx {
989   /* This flag is set by the callbacks, so we know we've done
990    * the callbacks as expected, and in the right sequence.
991    * 0 = not called, 1 = reply_cb called.
992    */
993   int cb_sequence;
994   struct guestfs_message_header hdr;
995   struct guestfs_message_error err;
996   struct guestfs_lvs_ret ret;
997 };
998
999 static void lvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1000 {
1001   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1002   struct lvs_ctx *ctx = (struct lvs_ctx *) data;
1003
1004   /* This should definitely not happen. */
1005   if (ctx->cb_sequence != 0) {
1006     ctx->cb_sequence = 9999;
1007     error (g, "%s: internal error: reply callback called twice", "guestfs_lvs");
1008     return;
1009   }
1010
1011   ml->main_loop_quit (ml, g);
1012
1013   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1014     error (g, "%s: failed to parse reply header", "guestfs_lvs");
1015     return;
1016   }
1017   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1018     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1019       error (g, "%s: failed to parse reply error", "guestfs_lvs");
1020       return;
1021     }
1022     goto done;
1023   }
1024   if (!xdr_guestfs_lvs_ret (xdr, &ctx->ret)) {
1025     error (g, "%s: failed to parse reply", "guestfs_lvs");
1026     return;
1027   }
1028  done:
1029   ctx->cb_sequence = 1;
1030 }
1031
1032 char **guestfs_lvs (guestfs_h *g)
1033 {
1034   struct lvs_ctx ctx;
1035   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1036   int serial;
1037
1038   if (check_state (g, "guestfs_lvs") == -1) return NULL;
1039   guestfs_set_busy (g);
1040
1041   memset (&ctx, 0, sizeof ctx);
1042
1043   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS, NULL, NULL);
1044   if (serial == -1) {
1045     guestfs_set_ready (g);
1046     return NULL;
1047   }
1048
1049   guestfs__switch_to_receiving (g);
1050   ctx.cb_sequence = 0;
1051   guestfs_set_reply_callback (g, lvs_reply_cb, &ctx);
1052   (void) ml->main_loop_run (ml, g);
1053   guestfs_set_reply_callback (g, NULL, NULL);
1054   if (ctx.cb_sequence != 1) {
1055     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs");
1056     guestfs_set_ready (g);
1057     return NULL;
1058   }
1059
1060   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS, serial) == -1) {
1061     guestfs_set_ready (g);
1062     return NULL;
1063   }
1064
1065   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1066     error (g, "%s", ctx.err.error_message);
1067     guestfs_set_ready (g);
1068     return NULL;
1069   }
1070
1071   guestfs_set_ready (g);
1072   /* caller will free this, but we need to add a NULL entry */
1073   ctx.ret.logvols.logvols_val =
1074     safe_realloc (g, ctx.ret.logvols.logvols_val,
1075                   sizeof (char *) * (ctx.ret.logvols.logvols_len + 1));
1076   ctx.ret.logvols.logvols_val[ctx.ret.logvols.logvols_len] = NULL;
1077   return ctx.ret.logvols.logvols_val;
1078 }
1079
1080 struct pvs_full_ctx {
1081   /* This flag is set by the callbacks, so we know we've done
1082    * the callbacks as expected, and in the right sequence.
1083    * 0 = not called, 1 = reply_cb called.
1084    */
1085   int cb_sequence;
1086   struct guestfs_message_header hdr;
1087   struct guestfs_message_error err;
1088   struct guestfs_pvs_full_ret ret;
1089 };
1090
1091 static void pvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1092 {
1093   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1094   struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data;
1095
1096   /* This should definitely not happen. */
1097   if (ctx->cb_sequence != 0) {
1098     ctx->cb_sequence = 9999;
1099     error (g, "%s: internal error: reply callback called twice", "guestfs_pvs_full");
1100     return;
1101   }
1102
1103   ml->main_loop_quit (ml, g);
1104
1105   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1106     error (g, "%s: failed to parse reply header", "guestfs_pvs_full");
1107     return;
1108   }
1109   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1110     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1111       error (g, "%s: failed to parse reply error", "guestfs_pvs_full");
1112       return;
1113     }
1114     goto done;
1115   }
1116   if (!xdr_guestfs_pvs_full_ret (xdr, &ctx->ret)) {
1117     error (g, "%s: failed to parse reply", "guestfs_pvs_full");
1118     return;
1119   }
1120  done:
1121   ctx->cb_sequence = 1;
1122 }
1123
1124 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
1125 {
1126   struct pvs_full_ctx ctx;
1127   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1128   int serial;
1129
1130   if (check_state (g, "guestfs_pvs_full") == -1) return NULL;
1131   guestfs_set_busy (g);
1132
1133   memset (&ctx, 0, sizeof ctx);
1134
1135   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
1136   if (serial == -1) {
1137     guestfs_set_ready (g);
1138     return NULL;
1139   }
1140
1141   guestfs__switch_to_receiving (g);
1142   ctx.cb_sequence = 0;
1143   guestfs_set_reply_callback (g, pvs_full_reply_cb, &ctx);
1144   (void) ml->main_loop_run (ml, g);
1145   guestfs_set_reply_callback (g, NULL, NULL);
1146   if (ctx.cb_sequence != 1) {
1147     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full");
1148     guestfs_set_ready (g);
1149     return NULL;
1150   }
1151
1152   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1) {
1153     guestfs_set_ready (g);
1154     return NULL;
1155   }
1156
1157   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1158     error (g, "%s", ctx.err.error_message);
1159     guestfs_set_ready (g);
1160     return NULL;
1161   }
1162
1163   guestfs_set_ready (g);
1164   /* caller will free this */
1165   return safe_memdup (g, &ctx.ret.physvols, sizeof (ctx.ret.physvols));
1166 }
1167
1168 struct vgs_full_ctx {
1169   /* This flag is set by the callbacks, so we know we've done
1170    * the callbacks as expected, and in the right sequence.
1171    * 0 = not called, 1 = reply_cb called.
1172    */
1173   int cb_sequence;
1174   struct guestfs_message_header hdr;
1175   struct guestfs_message_error err;
1176   struct guestfs_vgs_full_ret ret;
1177 };
1178
1179 static void vgs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1180 {
1181   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1182   struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data;
1183
1184   /* This should definitely not happen. */
1185   if (ctx->cb_sequence != 0) {
1186     ctx->cb_sequence = 9999;
1187     error (g, "%s: internal error: reply callback called twice", "guestfs_vgs_full");
1188     return;
1189   }
1190
1191   ml->main_loop_quit (ml, g);
1192
1193   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1194     error (g, "%s: failed to parse reply header", "guestfs_vgs_full");
1195     return;
1196   }
1197   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1198     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1199       error (g, "%s: failed to parse reply error", "guestfs_vgs_full");
1200       return;
1201     }
1202     goto done;
1203   }
1204   if (!xdr_guestfs_vgs_full_ret (xdr, &ctx->ret)) {
1205     error (g, "%s: failed to parse reply", "guestfs_vgs_full");
1206     return;
1207   }
1208  done:
1209   ctx->cb_sequence = 1;
1210 }
1211
1212 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
1213 {
1214   struct vgs_full_ctx ctx;
1215   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1216   int serial;
1217
1218   if (check_state (g, "guestfs_vgs_full") == -1) return NULL;
1219   guestfs_set_busy (g);
1220
1221   memset (&ctx, 0, sizeof ctx);
1222
1223   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
1224   if (serial == -1) {
1225     guestfs_set_ready (g);
1226     return NULL;
1227   }
1228
1229   guestfs__switch_to_receiving (g);
1230   ctx.cb_sequence = 0;
1231   guestfs_set_reply_callback (g, vgs_full_reply_cb, &ctx);
1232   (void) ml->main_loop_run (ml, g);
1233   guestfs_set_reply_callback (g, NULL, NULL);
1234   if (ctx.cb_sequence != 1) {
1235     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full");
1236     guestfs_set_ready (g);
1237     return NULL;
1238   }
1239
1240   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1) {
1241     guestfs_set_ready (g);
1242     return NULL;
1243   }
1244
1245   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1246     error (g, "%s", ctx.err.error_message);
1247     guestfs_set_ready (g);
1248     return NULL;
1249   }
1250
1251   guestfs_set_ready (g);
1252   /* caller will free this */
1253   return safe_memdup (g, &ctx.ret.volgroups, sizeof (ctx.ret.volgroups));
1254 }
1255
1256 struct lvs_full_ctx {
1257   /* This flag is set by the callbacks, so we know we've done
1258    * the callbacks as expected, and in the right sequence.
1259    * 0 = not called, 1 = reply_cb called.
1260    */
1261   int cb_sequence;
1262   struct guestfs_message_header hdr;
1263   struct guestfs_message_error err;
1264   struct guestfs_lvs_full_ret ret;
1265 };
1266
1267 static void lvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1268 {
1269   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1270   struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data;
1271
1272   /* This should definitely not happen. */
1273   if (ctx->cb_sequence != 0) {
1274     ctx->cb_sequence = 9999;
1275     error (g, "%s: internal error: reply callback called twice", "guestfs_lvs_full");
1276     return;
1277   }
1278
1279   ml->main_loop_quit (ml, g);
1280
1281   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1282     error (g, "%s: failed to parse reply header", "guestfs_lvs_full");
1283     return;
1284   }
1285   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1286     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1287       error (g, "%s: failed to parse reply error", "guestfs_lvs_full");
1288       return;
1289     }
1290     goto done;
1291   }
1292   if (!xdr_guestfs_lvs_full_ret (xdr, &ctx->ret)) {
1293     error (g, "%s: failed to parse reply", "guestfs_lvs_full");
1294     return;
1295   }
1296  done:
1297   ctx->cb_sequence = 1;
1298 }
1299
1300 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
1301 {
1302   struct lvs_full_ctx ctx;
1303   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1304   int serial;
1305
1306   if (check_state (g, "guestfs_lvs_full") == -1) return NULL;
1307   guestfs_set_busy (g);
1308
1309   memset (&ctx, 0, sizeof ctx);
1310
1311   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
1312   if (serial == -1) {
1313     guestfs_set_ready (g);
1314     return NULL;
1315   }
1316
1317   guestfs__switch_to_receiving (g);
1318   ctx.cb_sequence = 0;
1319   guestfs_set_reply_callback (g, lvs_full_reply_cb, &ctx);
1320   (void) ml->main_loop_run (ml, g);
1321   guestfs_set_reply_callback (g, NULL, NULL);
1322   if (ctx.cb_sequence != 1) {
1323     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full");
1324     guestfs_set_ready (g);
1325     return NULL;
1326   }
1327
1328   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1) {
1329     guestfs_set_ready (g);
1330     return NULL;
1331   }
1332
1333   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1334     error (g, "%s", ctx.err.error_message);
1335     guestfs_set_ready (g);
1336     return NULL;
1337   }
1338
1339   guestfs_set_ready (g);
1340   /* caller will free this */
1341   return safe_memdup (g, &ctx.ret.logvols, sizeof (ctx.ret.logvols));
1342 }
1343
1344 struct read_lines_ctx {
1345   /* This flag is set by the callbacks, so we know we've done
1346    * the callbacks as expected, and in the right sequence.
1347    * 0 = not called, 1 = reply_cb called.
1348    */
1349   int cb_sequence;
1350   struct guestfs_message_header hdr;
1351   struct guestfs_message_error err;
1352   struct guestfs_read_lines_ret ret;
1353 };
1354
1355 static void read_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1356 {
1357   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1358   struct read_lines_ctx *ctx = (struct read_lines_ctx *) data;
1359
1360   /* This should definitely not happen. */
1361   if (ctx->cb_sequence != 0) {
1362     ctx->cb_sequence = 9999;
1363     error (g, "%s: internal error: reply callback called twice", "guestfs_read_lines");
1364     return;
1365   }
1366
1367   ml->main_loop_quit (ml, g);
1368
1369   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1370     error (g, "%s: failed to parse reply header", "guestfs_read_lines");
1371     return;
1372   }
1373   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1374     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1375       error (g, "%s: failed to parse reply error", "guestfs_read_lines");
1376       return;
1377     }
1378     goto done;
1379   }
1380   if (!xdr_guestfs_read_lines_ret (xdr, &ctx->ret)) {
1381     error (g, "%s: failed to parse reply", "guestfs_read_lines");
1382     return;
1383   }
1384  done:
1385   ctx->cb_sequence = 1;
1386 }
1387
1388 char **guestfs_read_lines (guestfs_h *g,
1389                 const char *path)
1390 {
1391   struct guestfs_read_lines_args args;
1392   struct read_lines_ctx ctx;
1393   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1394   int serial;
1395
1396   if (check_state (g, "guestfs_read_lines") == -1) return NULL;
1397   guestfs_set_busy (g);
1398
1399   memset (&ctx, 0, sizeof ctx);
1400
1401   args.path = (char *) path;
1402   serial = guestfs__send_sync (g, GUESTFS_PROC_READ_LINES,
1403         (xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args);
1404   if (serial == -1) {
1405     guestfs_set_ready (g);
1406     return NULL;
1407   }
1408
1409   guestfs__switch_to_receiving (g);
1410   ctx.cb_sequence = 0;
1411   guestfs_set_reply_callback (g, read_lines_reply_cb, &ctx);
1412   (void) ml->main_loop_run (ml, g);
1413   guestfs_set_reply_callback (g, NULL, NULL);
1414   if (ctx.cb_sequence != 1) {
1415     error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines");
1416     guestfs_set_ready (g);
1417     return NULL;
1418   }
1419
1420   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_READ_LINES, serial) == -1) {
1421     guestfs_set_ready (g);
1422     return NULL;
1423   }
1424
1425   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1426     error (g, "%s", ctx.err.error_message);
1427     guestfs_set_ready (g);
1428     return NULL;
1429   }
1430
1431   guestfs_set_ready (g);
1432   /* caller will free this, but we need to add a NULL entry */
1433   ctx.ret.lines.lines_val =
1434     safe_realloc (g, ctx.ret.lines.lines_val,
1435                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
1436   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
1437   return ctx.ret.lines.lines_val;
1438 }
1439
1440 struct aug_init_ctx {
1441   /* This flag is set by the callbacks, so we know we've done
1442    * the callbacks as expected, and in the right sequence.
1443    * 0 = not called, 1 = reply_cb called.
1444    */
1445   int cb_sequence;
1446   struct guestfs_message_header hdr;
1447   struct guestfs_message_error err;
1448 };
1449
1450 static void aug_init_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1451 {
1452   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1453   struct aug_init_ctx *ctx = (struct aug_init_ctx *) data;
1454
1455   /* This should definitely not happen. */
1456   if (ctx->cb_sequence != 0) {
1457     ctx->cb_sequence = 9999;
1458     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_init");
1459     return;
1460   }
1461
1462   ml->main_loop_quit (ml, g);
1463
1464   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1465     error (g, "%s: failed to parse reply header", "guestfs_aug_init");
1466     return;
1467   }
1468   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1469     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1470       error (g, "%s: failed to parse reply error", "guestfs_aug_init");
1471       return;
1472     }
1473     goto done;
1474   }
1475  done:
1476   ctx->cb_sequence = 1;
1477 }
1478
1479 int guestfs_aug_init (guestfs_h *g,
1480                 const char *root,
1481                 int flags)
1482 {
1483   struct guestfs_aug_init_args args;
1484   struct aug_init_ctx ctx;
1485   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1486   int serial;
1487
1488   if (check_state (g, "guestfs_aug_init") == -1) return -1;
1489   guestfs_set_busy (g);
1490
1491   memset (&ctx, 0, sizeof ctx);
1492
1493   args.root = (char *) root;
1494   args.flags = flags;
1495   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INIT,
1496         (xdrproc_t) xdr_guestfs_aug_init_args, (char *) &args);
1497   if (serial == -1) {
1498     guestfs_set_ready (g);
1499     return -1;
1500   }
1501
1502   guestfs__switch_to_receiving (g);
1503   ctx.cb_sequence = 0;
1504   guestfs_set_reply_callback (g, aug_init_reply_cb, &ctx);
1505   (void) ml->main_loop_run (ml, g);
1506   guestfs_set_reply_callback (g, NULL, NULL);
1507   if (ctx.cb_sequence != 1) {
1508     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init");
1509     guestfs_set_ready (g);
1510     return -1;
1511   }
1512
1513   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1) {
1514     guestfs_set_ready (g);
1515     return -1;
1516   }
1517
1518   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1519     error (g, "%s", ctx.err.error_message);
1520     guestfs_set_ready (g);
1521     return -1;
1522   }
1523
1524   guestfs_set_ready (g);
1525   return 0;
1526 }
1527
1528 struct aug_close_ctx {
1529   /* This flag is set by the callbacks, so we know we've done
1530    * the callbacks as expected, and in the right sequence.
1531    * 0 = not called, 1 = reply_cb called.
1532    */
1533   int cb_sequence;
1534   struct guestfs_message_header hdr;
1535   struct guestfs_message_error err;
1536 };
1537
1538 static void aug_close_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1539 {
1540   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1541   struct aug_close_ctx *ctx = (struct aug_close_ctx *) data;
1542
1543   /* This should definitely not happen. */
1544   if (ctx->cb_sequence != 0) {
1545     ctx->cb_sequence = 9999;
1546     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_close");
1547     return;
1548   }
1549
1550   ml->main_loop_quit (ml, g);
1551
1552   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1553     error (g, "%s: failed to parse reply header", "guestfs_aug_close");
1554     return;
1555   }
1556   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1557     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1558       error (g, "%s: failed to parse reply error", "guestfs_aug_close");
1559       return;
1560     }
1561     goto done;
1562   }
1563  done:
1564   ctx->cb_sequence = 1;
1565 }
1566
1567 int guestfs_aug_close (guestfs_h *g)
1568 {
1569   struct aug_close_ctx ctx;
1570   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1571   int serial;
1572
1573   if (check_state (g, "guestfs_aug_close") == -1) return -1;
1574   guestfs_set_busy (g);
1575
1576   memset (&ctx, 0, sizeof ctx);
1577
1578   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
1579   if (serial == -1) {
1580     guestfs_set_ready (g);
1581     return -1;
1582   }
1583
1584   guestfs__switch_to_receiving (g);
1585   ctx.cb_sequence = 0;
1586   guestfs_set_reply_callback (g, aug_close_reply_cb, &ctx);
1587   (void) ml->main_loop_run (ml, g);
1588   guestfs_set_reply_callback (g, NULL, NULL);
1589   if (ctx.cb_sequence != 1) {
1590     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close");
1591     guestfs_set_ready (g);
1592     return -1;
1593   }
1594
1595   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1) {
1596     guestfs_set_ready (g);
1597     return -1;
1598   }
1599
1600   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1601     error (g, "%s", ctx.err.error_message);
1602     guestfs_set_ready (g);
1603     return -1;
1604   }
1605
1606   guestfs_set_ready (g);
1607   return 0;
1608 }
1609
1610 struct aug_defvar_ctx {
1611   /* This flag is set by the callbacks, so we know we've done
1612    * the callbacks as expected, and in the right sequence.
1613    * 0 = not called, 1 = reply_cb called.
1614    */
1615   int cb_sequence;
1616   struct guestfs_message_header hdr;
1617   struct guestfs_message_error err;
1618   struct guestfs_aug_defvar_ret ret;
1619 };
1620
1621 static void aug_defvar_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1622 {
1623   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1624   struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data;
1625
1626   /* This should definitely not happen. */
1627   if (ctx->cb_sequence != 0) {
1628     ctx->cb_sequence = 9999;
1629     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defvar");
1630     return;
1631   }
1632
1633   ml->main_loop_quit (ml, g);
1634
1635   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1636     error (g, "%s: failed to parse reply header", "guestfs_aug_defvar");
1637     return;
1638   }
1639   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1640     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1641       error (g, "%s: failed to parse reply error", "guestfs_aug_defvar");
1642       return;
1643     }
1644     goto done;
1645   }
1646   if (!xdr_guestfs_aug_defvar_ret (xdr, &ctx->ret)) {
1647     error (g, "%s: failed to parse reply", "guestfs_aug_defvar");
1648     return;
1649   }
1650  done:
1651   ctx->cb_sequence = 1;
1652 }
1653
1654 int guestfs_aug_defvar (guestfs_h *g,
1655                 const char *name,
1656                 const char *expr)
1657 {
1658   struct guestfs_aug_defvar_args args;
1659   struct aug_defvar_ctx ctx;
1660   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1661   int serial;
1662
1663   if (check_state (g, "guestfs_aug_defvar") == -1) return -1;
1664   guestfs_set_busy (g);
1665
1666   memset (&ctx, 0, sizeof ctx);
1667
1668   args.name = (char *) name;
1669   args.expr = expr ? (char **) &expr : NULL;
1670   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFVAR,
1671         (xdrproc_t) xdr_guestfs_aug_defvar_args, (char *) &args);
1672   if (serial == -1) {
1673     guestfs_set_ready (g);
1674     return -1;
1675   }
1676
1677   guestfs__switch_to_receiving (g);
1678   ctx.cb_sequence = 0;
1679   guestfs_set_reply_callback (g, aug_defvar_reply_cb, &ctx);
1680   (void) ml->main_loop_run (ml, g);
1681   guestfs_set_reply_callback (g, NULL, NULL);
1682   if (ctx.cb_sequence != 1) {
1683     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar");
1684     guestfs_set_ready (g);
1685     return -1;
1686   }
1687
1688   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1) {
1689     guestfs_set_ready (g);
1690     return -1;
1691   }
1692
1693   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1694     error (g, "%s", ctx.err.error_message);
1695     guestfs_set_ready (g);
1696     return -1;
1697   }
1698
1699   guestfs_set_ready (g);
1700   return ctx.ret.nrnodes;
1701 }
1702
1703 struct aug_defnode_ctx {
1704   /* This flag is set by the callbacks, so we know we've done
1705    * the callbacks as expected, and in the right sequence.
1706    * 0 = not called, 1 = reply_cb called.
1707    */
1708   int cb_sequence;
1709   struct guestfs_message_header hdr;
1710   struct guestfs_message_error err;
1711   struct guestfs_aug_defnode_ret ret;
1712 };
1713
1714 static void aug_defnode_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1715 {
1716   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1717   struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data;
1718
1719   /* This should definitely not happen. */
1720   if (ctx->cb_sequence != 0) {
1721     ctx->cb_sequence = 9999;
1722     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defnode");
1723     return;
1724   }
1725
1726   ml->main_loop_quit (ml, g);
1727
1728   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1729     error (g, "%s: failed to parse reply header", "guestfs_aug_defnode");
1730     return;
1731   }
1732   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1733     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1734       error (g, "%s: failed to parse reply error", "guestfs_aug_defnode");
1735       return;
1736     }
1737     goto done;
1738   }
1739   if (!xdr_guestfs_aug_defnode_ret (xdr, &ctx->ret)) {
1740     error (g, "%s: failed to parse reply", "guestfs_aug_defnode");
1741     return;
1742   }
1743  done:
1744   ctx->cb_sequence = 1;
1745 }
1746
1747 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
1748                 const char *name,
1749                 const char *expr,
1750                 const char *val)
1751 {
1752   struct guestfs_aug_defnode_args args;
1753   struct aug_defnode_ctx ctx;
1754   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1755   int serial;
1756
1757   if (check_state (g, "guestfs_aug_defnode") == -1) return NULL;
1758   guestfs_set_busy (g);
1759
1760   memset (&ctx, 0, sizeof ctx);
1761
1762   args.name = (char *) name;
1763   args.expr = (char *) expr;
1764   args.val = (char *) val;
1765   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFNODE,
1766         (xdrproc_t) xdr_guestfs_aug_defnode_args, (char *) &args);
1767   if (serial == -1) {
1768     guestfs_set_ready (g);
1769     return NULL;
1770   }
1771
1772   guestfs__switch_to_receiving (g);
1773   ctx.cb_sequence = 0;
1774   guestfs_set_reply_callback (g, aug_defnode_reply_cb, &ctx);
1775   (void) ml->main_loop_run (ml, g);
1776   guestfs_set_reply_callback (g, NULL, NULL);
1777   if (ctx.cb_sequence != 1) {
1778     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode");
1779     guestfs_set_ready (g);
1780     return NULL;
1781   }
1782
1783   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1) {
1784     guestfs_set_ready (g);
1785     return NULL;
1786   }
1787
1788   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1789     error (g, "%s", ctx.err.error_message);
1790     guestfs_set_ready (g);
1791     return NULL;
1792   }
1793
1794   guestfs_set_ready (g);
1795   /* caller with free this */
1796   return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));
1797 }
1798
1799 struct aug_get_ctx {
1800   /* This flag is set by the callbacks, so we know we've done
1801    * the callbacks as expected, and in the right sequence.
1802    * 0 = not called, 1 = reply_cb called.
1803    */
1804   int cb_sequence;
1805   struct guestfs_message_header hdr;
1806   struct guestfs_message_error err;
1807   struct guestfs_aug_get_ret ret;
1808 };
1809
1810 static void aug_get_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1811 {
1812   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1813   struct aug_get_ctx *ctx = (struct aug_get_ctx *) data;
1814
1815   /* This should definitely not happen. */
1816   if (ctx->cb_sequence != 0) {
1817     ctx->cb_sequence = 9999;
1818     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_get");
1819     return;
1820   }
1821
1822   ml->main_loop_quit (ml, g);
1823
1824   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1825     error (g, "%s: failed to parse reply header", "guestfs_aug_get");
1826     return;
1827   }
1828   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1829     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1830       error (g, "%s: failed to parse reply error", "guestfs_aug_get");
1831       return;
1832     }
1833     goto done;
1834   }
1835   if (!xdr_guestfs_aug_get_ret (xdr, &ctx->ret)) {
1836     error (g, "%s: failed to parse reply", "guestfs_aug_get");
1837     return;
1838   }
1839  done:
1840   ctx->cb_sequence = 1;
1841 }
1842
1843 char *guestfs_aug_get (guestfs_h *g,
1844                 const char *path)
1845 {
1846   struct guestfs_aug_get_args args;
1847   struct aug_get_ctx ctx;
1848   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1849   int serial;
1850
1851   if (check_state (g, "guestfs_aug_get") == -1) return NULL;
1852   guestfs_set_busy (g);
1853
1854   memset (&ctx, 0, sizeof ctx);
1855
1856   args.path = (char *) path;
1857   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_GET,
1858         (xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args);
1859   if (serial == -1) {
1860     guestfs_set_ready (g);
1861     return NULL;
1862   }
1863
1864   guestfs__switch_to_receiving (g);
1865   ctx.cb_sequence = 0;
1866   guestfs_set_reply_callback (g, aug_get_reply_cb, &ctx);
1867   (void) ml->main_loop_run (ml, g);
1868   guestfs_set_reply_callback (g, NULL, NULL);
1869   if (ctx.cb_sequence != 1) {
1870     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get");
1871     guestfs_set_ready (g);
1872     return NULL;
1873   }
1874
1875   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_GET, serial) == -1) {
1876     guestfs_set_ready (g);
1877     return NULL;
1878   }
1879
1880   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1881     error (g, "%s", ctx.err.error_message);
1882     guestfs_set_ready (g);
1883     return NULL;
1884   }
1885
1886   guestfs_set_ready (g);
1887   return ctx.ret.val; /* caller will free */
1888 }
1889
1890 struct aug_set_ctx {
1891   /* This flag is set by the callbacks, so we know we've done
1892    * the callbacks as expected, and in the right sequence.
1893    * 0 = not called, 1 = reply_cb called.
1894    */
1895   int cb_sequence;
1896   struct guestfs_message_header hdr;
1897   struct guestfs_message_error err;
1898 };
1899
1900 static void aug_set_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1901 {
1902   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1903   struct aug_set_ctx *ctx = (struct aug_set_ctx *) data;
1904
1905   /* This should definitely not happen. */
1906   if (ctx->cb_sequence != 0) {
1907     ctx->cb_sequence = 9999;
1908     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_set");
1909     return;
1910   }
1911
1912   ml->main_loop_quit (ml, g);
1913
1914   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1915     error (g, "%s: failed to parse reply header", "guestfs_aug_set");
1916     return;
1917   }
1918   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1919     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1920       error (g, "%s: failed to parse reply error", "guestfs_aug_set");
1921       return;
1922     }
1923     goto done;
1924   }
1925  done:
1926   ctx->cb_sequence = 1;
1927 }
1928
1929 int guestfs_aug_set (guestfs_h *g,
1930                 const char *path,
1931                 const char *val)
1932 {
1933   struct guestfs_aug_set_args args;
1934   struct aug_set_ctx ctx;
1935   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1936   int serial;
1937
1938   if (check_state (g, "guestfs_aug_set") == -1) return -1;
1939   guestfs_set_busy (g);
1940
1941   memset (&ctx, 0, sizeof ctx);
1942
1943   args.path = (char *) path;
1944   args.val = (char *) val;
1945   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SET,
1946         (xdrproc_t) xdr_guestfs_aug_set_args, (char *) &args);
1947   if (serial == -1) {
1948     guestfs_set_ready (g);
1949     return -1;
1950   }
1951
1952   guestfs__switch_to_receiving (g);
1953   ctx.cb_sequence = 0;
1954   guestfs_set_reply_callback (g, aug_set_reply_cb, &ctx);
1955   (void) ml->main_loop_run (ml, g);
1956   guestfs_set_reply_callback (g, NULL, NULL);
1957   if (ctx.cb_sequence != 1) {
1958     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set");
1959     guestfs_set_ready (g);
1960     return -1;
1961   }
1962
1963   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SET, serial) == -1) {
1964     guestfs_set_ready (g);
1965     return -1;
1966   }
1967
1968   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1969     error (g, "%s", ctx.err.error_message);
1970     guestfs_set_ready (g);
1971     return -1;
1972   }
1973
1974   guestfs_set_ready (g);
1975   return 0;
1976 }
1977
1978 struct aug_insert_ctx {
1979   /* This flag is set by the callbacks, so we know we've done
1980    * the callbacks as expected, and in the right sequence.
1981    * 0 = not called, 1 = reply_cb called.
1982    */
1983   int cb_sequence;
1984   struct guestfs_message_header hdr;
1985   struct guestfs_message_error err;
1986 };
1987
1988 static void aug_insert_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1989 {
1990   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1991   struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data;
1992
1993   /* This should definitely not happen. */
1994   if (ctx->cb_sequence != 0) {
1995     ctx->cb_sequence = 9999;
1996     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_insert");
1997     return;
1998   }
1999
2000   ml->main_loop_quit (ml, g);
2001
2002   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2003     error (g, "%s: failed to parse reply header", "guestfs_aug_insert");
2004     return;
2005   }
2006   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2007     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2008       error (g, "%s: failed to parse reply error", "guestfs_aug_insert");
2009       return;
2010     }
2011     goto done;
2012   }
2013  done:
2014   ctx->cb_sequence = 1;
2015 }
2016
2017 int guestfs_aug_insert (guestfs_h *g,
2018                 const char *path,
2019                 const char *label,
2020                 int before)
2021 {
2022   struct guestfs_aug_insert_args args;
2023   struct aug_insert_ctx ctx;
2024   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2025   int serial;
2026
2027   if (check_state (g, "guestfs_aug_insert") == -1) return -1;
2028   guestfs_set_busy (g);
2029
2030   memset (&ctx, 0, sizeof ctx);
2031
2032   args.path = (char *) path;
2033   args.label = (char *) label;
2034   args.before = before;
2035   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INSERT,
2036         (xdrproc_t) xdr_guestfs_aug_insert_args, (char *) &args);
2037   if (serial == -1) {
2038     guestfs_set_ready (g);
2039     return -1;
2040   }
2041
2042   guestfs__switch_to_receiving (g);
2043   ctx.cb_sequence = 0;
2044   guestfs_set_reply_callback (g, aug_insert_reply_cb, &ctx);
2045   (void) ml->main_loop_run (ml, g);
2046   guestfs_set_reply_callback (g, NULL, NULL);
2047   if (ctx.cb_sequence != 1) {
2048     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert");
2049     guestfs_set_ready (g);
2050     return -1;
2051   }
2052
2053   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1) {
2054     guestfs_set_ready (g);
2055     return -1;
2056   }
2057
2058   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2059     error (g, "%s", ctx.err.error_message);
2060     guestfs_set_ready (g);
2061     return -1;
2062   }
2063
2064   guestfs_set_ready (g);
2065   return 0;
2066 }
2067
2068 struct aug_rm_ctx {
2069   /* This flag is set by the callbacks, so we know we've done
2070    * the callbacks as expected, and in the right sequence.
2071    * 0 = not called, 1 = reply_cb called.
2072    */
2073   int cb_sequence;
2074   struct guestfs_message_header hdr;
2075   struct guestfs_message_error err;
2076   struct guestfs_aug_rm_ret ret;
2077 };
2078
2079 static void aug_rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2080 {
2081   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2082   struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data;
2083
2084   /* This should definitely not happen. */
2085   if (ctx->cb_sequence != 0) {
2086     ctx->cb_sequence = 9999;
2087     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_rm");
2088     return;
2089   }
2090
2091   ml->main_loop_quit (ml, g);
2092
2093   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2094     error (g, "%s: failed to parse reply header", "guestfs_aug_rm");
2095     return;
2096   }
2097   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2098     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2099       error (g, "%s: failed to parse reply error", "guestfs_aug_rm");
2100       return;
2101     }
2102     goto done;
2103   }
2104   if (!xdr_guestfs_aug_rm_ret (xdr, &ctx->ret)) {
2105     error (g, "%s: failed to parse reply", "guestfs_aug_rm");
2106     return;
2107   }
2108  done:
2109   ctx->cb_sequence = 1;
2110 }
2111
2112 int guestfs_aug_rm (guestfs_h *g,
2113                 const char *path)
2114 {
2115   struct guestfs_aug_rm_args args;
2116   struct aug_rm_ctx ctx;
2117   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2118   int serial;
2119
2120   if (check_state (g, "guestfs_aug_rm") == -1) return -1;
2121   guestfs_set_busy (g);
2122
2123   memset (&ctx, 0, sizeof ctx);
2124
2125   args.path = (char *) path;
2126   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_RM,
2127         (xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args);
2128   if (serial == -1) {
2129     guestfs_set_ready (g);
2130     return -1;
2131   }
2132
2133   guestfs__switch_to_receiving (g);
2134   ctx.cb_sequence = 0;
2135   guestfs_set_reply_callback (g, aug_rm_reply_cb, &ctx);
2136   (void) ml->main_loop_run (ml, g);
2137   guestfs_set_reply_callback (g, NULL, NULL);
2138   if (ctx.cb_sequence != 1) {
2139     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm");
2140     guestfs_set_ready (g);
2141     return -1;
2142   }
2143
2144   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_RM, serial) == -1) {
2145     guestfs_set_ready (g);
2146     return -1;
2147   }
2148
2149   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2150     error (g, "%s", ctx.err.error_message);
2151     guestfs_set_ready (g);
2152     return -1;
2153   }
2154
2155   guestfs_set_ready (g);
2156   return ctx.ret.nrnodes;
2157 }
2158
2159 struct aug_mv_ctx {
2160   /* This flag is set by the callbacks, so we know we've done
2161    * the callbacks as expected, and in the right sequence.
2162    * 0 = not called, 1 = reply_cb called.
2163    */
2164   int cb_sequence;
2165   struct guestfs_message_header hdr;
2166   struct guestfs_message_error err;
2167 };
2168
2169 static void aug_mv_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2170 {
2171   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2172   struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data;
2173
2174   /* This should definitely not happen. */
2175   if (ctx->cb_sequence != 0) {
2176     ctx->cb_sequence = 9999;
2177     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_mv");
2178     return;
2179   }
2180
2181   ml->main_loop_quit (ml, g);
2182
2183   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2184     error (g, "%s: failed to parse reply header", "guestfs_aug_mv");
2185     return;
2186   }
2187   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2188     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2189       error (g, "%s: failed to parse reply error", "guestfs_aug_mv");
2190       return;
2191     }
2192     goto done;
2193   }
2194  done:
2195   ctx->cb_sequence = 1;
2196 }
2197
2198 int guestfs_aug_mv (guestfs_h *g,
2199                 const char *src,
2200                 const char *dest)
2201 {
2202   struct guestfs_aug_mv_args args;
2203   struct aug_mv_ctx ctx;
2204   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2205   int serial;
2206
2207   if (check_state (g, "guestfs_aug_mv") == -1) return -1;
2208   guestfs_set_busy (g);
2209
2210   memset (&ctx, 0, sizeof ctx);
2211
2212   args.src = (char *) src;
2213   args.dest = (char *) dest;
2214   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MV,
2215         (xdrproc_t) xdr_guestfs_aug_mv_args, (char *) &args);
2216   if (serial == -1) {
2217     guestfs_set_ready (g);
2218     return -1;
2219   }
2220
2221   guestfs__switch_to_receiving (g);
2222   ctx.cb_sequence = 0;
2223   guestfs_set_reply_callback (g, aug_mv_reply_cb, &ctx);
2224   (void) ml->main_loop_run (ml, g);
2225   guestfs_set_reply_callback (g, NULL, NULL);
2226   if (ctx.cb_sequence != 1) {
2227     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv");
2228     guestfs_set_ready (g);
2229     return -1;
2230   }
2231
2232   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MV, serial) == -1) {
2233     guestfs_set_ready (g);
2234     return -1;
2235   }
2236
2237   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2238     error (g, "%s", ctx.err.error_message);
2239     guestfs_set_ready (g);
2240     return -1;
2241   }
2242
2243   guestfs_set_ready (g);
2244   return 0;
2245 }
2246
2247 struct aug_match_ctx {
2248   /* This flag is set by the callbacks, so we know we've done
2249    * the callbacks as expected, and in the right sequence.
2250    * 0 = not called, 1 = reply_cb called.
2251    */
2252   int cb_sequence;
2253   struct guestfs_message_header hdr;
2254   struct guestfs_message_error err;
2255   struct guestfs_aug_match_ret ret;
2256 };
2257
2258 static void aug_match_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2259 {
2260   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2261   struct aug_match_ctx *ctx = (struct aug_match_ctx *) data;
2262
2263   /* This should definitely not happen. */
2264   if (ctx->cb_sequence != 0) {
2265     ctx->cb_sequence = 9999;
2266     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_match");
2267     return;
2268   }
2269
2270   ml->main_loop_quit (ml, g);
2271
2272   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2273     error (g, "%s: failed to parse reply header", "guestfs_aug_match");
2274     return;
2275   }
2276   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2277     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2278       error (g, "%s: failed to parse reply error", "guestfs_aug_match");
2279       return;
2280     }
2281     goto done;
2282   }
2283   if (!xdr_guestfs_aug_match_ret (xdr, &ctx->ret)) {
2284     error (g, "%s: failed to parse reply", "guestfs_aug_match");
2285     return;
2286   }
2287  done:
2288   ctx->cb_sequence = 1;
2289 }
2290
2291 char **guestfs_aug_match (guestfs_h *g,
2292                 const char *path)
2293 {
2294   struct guestfs_aug_match_args args;
2295   struct aug_match_ctx ctx;
2296   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2297   int serial;
2298
2299   if (check_state (g, "guestfs_aug_match") == -1) return NULL;
2300   guestfs_set_busy (g);
2301
2302   memset (&ctx, 0, sizeof ctx);
2303
2304   args.path = (char *) path;
2305   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MATCH,
2306         (xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args);
2307   if (serial == -1) {
2308     guestfs_set_ready (g);
2309     return NULL;
2310   }
2311
2312   guestfs__switch_to_receiving (g);
2313   ctx.cb_sequence = 0;
2314   guestfs_set_reply_callback (g, aug_match_reply_cb, &ctx);
2315   (void) ml->main_loop_run (ml, g);
2316   guestfs_set_reply_callback (g, NULL, NULL);
2317   if (ctx.cb_sequence != 1) {
2318     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match");
2319     guestfs_set_ready (g);
2320     return NULL;
2321   }
2322
2323   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1) {
2324     guestfs_set_ready (g);
2325     return NULL;
2326   }
2327
2328   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2329     error (g, "%s", ctx.err.error_message);
2330     guestfs_set_ready (g);
2331     return NULL;
2332   }
2333
2334   guestfs_set_ready (g);
2335   /* caller will free this, but we need to add a NULL entry */
2336   ctx.ret.matches.matches_val =
2337     safe_realloc (g, ctx.ret.matches.matches_val,
2338                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2339   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2340   return ctx.ret.matches.matches_val;
2341 }
2342
2343 struct aug_save_ctx {
2344   /* This flag is set by the callbacks, so we know we've done
2345    * the callbacks as expected, and in the right sequence.
2346    * 0 = not called, 1 = reply_cb called.
2347    */
2348   int cb_sequence;
2349   struct guestfs_message_header hdr;
2350   struct guestfs_message_error err;
2351 };
2352
2353 static void aug_save_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2354 {
2355   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2356   struct aug_save_ctx *ctx = (struct aug_save_ctx *) data;
2357
2358   /* This should definitely not happen. */
2359   if (ctx->cb_sequence != 0) {
2360     ctx->cb_sequence = 9999;
2361     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_save");
2362     return;
2363   }
2364
2365   ml->main_loop_quit (ml, g);
2366
2367   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2368     error (g, "%s: failed to parse reply header", "guestfs_aug_save");
2369     return;
2370   }
2371   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2372     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2373       error (g, "%s: failed to parse reply error", "guestfs_aug_save");
2374       return;
2375     }
2376     goto done;
2377   }
2378  done:
2379   ctx->cb_sequence = 1;
2380 }
2381
2382 int guestfs_aug_save (guestfs_h *g)
2383 {
2384   struct aug_save_ctx ctx;
2385   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2386   int serial;
2387
2388   if (check_state (g, "guestfs_aug_save") == -1) return -1;
2389   guestfs_set_busy (g);
2390
2391   memset (&ctx, 0, sizeof ctx);
2392
2393   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
2394   if (serial == -1) {
2395     guestfs_set_ready (g);
2396     return -1;
2397   }
2398
2399   guestfs__switch_to_receiving (g);
2400   ctx.cb_sequence = 0;
2401   guestfs_set_reply_callback (g, aug_save_reply_cb, &ctx);
2402   (void) ml->main_loop_run (ml, g);
2403   guestfs_set_reply_callback (g, NULL, NULL);
2404   if (ctx.cb_sequence != 1) {
2405     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save");
2406     guestfs_set_ready (g);
2407     return -1;
2408   }
2409
2410   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1) {
2411     guestfs_set_ready (g);
2412     return -1;
2413   }
2414
2415   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2416     error (g, "%s", ctx.err.error_message);
2417     guestfs_set_ready (g);
2418     return -1;
2419   }
2420
2421   guestfs_set_ready (g);
2422   return 0;
2423 }
2424
2425 struct aug_load_ctx {
2426   /* This flag is set by the callbacks, so we know we've done
2427    * the callbacks as expected, and in the right sequence.
2428    * 0 = not called, 1 = reply_cb called.
2429    */
2430   int cb_sequence;
2431   struct guestfs_message_header hdr;
2432   struct guestfs_message_error err;
2433 };
2434
2435 static void aug_load_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2436 {
2437   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2438   struct aug_load_ctx *ctx = (struct aug_load_ctx *) data;
2439
2440   /* This should definitely not happen. */
2441   if (ctx->cb_sequence != 0) {
2442     ctx->cb_sequence = 9999;
2443     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_load");
2444     return;
2445   }
2446
2447   ml->main_loop_quit (ml, g);
2448
2449   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2450     error (g, "%s: failed to parse reply header", "guestfs_aug_load");
2451     return;
2452   }
2453   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2454     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2455       error (g, "%s: failed to parse reply error", "guestfs_aug_load");
2456       return;
2457     }
2458     goto done;
2459   }
2460  done:
2461   ctx->cb_sequence = 1;
2462 }
2463
2464 int guestfs_aug_load (guestfs_h *g)
2465 {
2466   struct aug_load_ctx ctx;
2467   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2468   int serial;
2469
2470   if (check_state (g, "guestfs_aug_load") == -1) return -1;
2471   guestfs_set_busy (g);
2472
2473   memset (&ctx, 0, sizeof ctx);
2474
2475   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
2476   if (serial == -1) {
2477     guestfs_set_ready (g);
2478     return -1;
2479   }
2480
2481   guestfs__switch_to_receiving (g);
2482   ctx.cb_sequence = 0;
2483   guestfs_set_reply_callback (g, aug_load_reply_cb, &ctx);
2484   (void) ml->main_loop_run (ml, g);
2485   guestfs_set_reply_callback (g, NULL, NULL);
2486   if (ctx.cb_sequence != 1) {
2487     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load");
2488     guestfs_set_ready (g);
2489     return -1;
2490   }
2491
2492   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1) {
2493     guestfs_set_ready (g);
2494     return -1;
2495   }
2496
2497   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2498     error (g, "%s", ctx.err.error_message);
2499     guestfs_set_ready (g);
2500     return -1;
2501   }
2502
2503   guestfs_set_ready (g);
2504   return 0;
2505 }
2506
2507 struct aug_ls_ctx {
2508   /* This flag is set by the callbacks, so we know we've done
2509    * the callbacks as expected, and in the right sequence.
2510    * 0 = not called, 1 = reply_cb called.
2511    */
2512   int cb_sequence;
2513   struct guestfs_message_header hdr;
2514   struct guestfs_message_error err;
2515   struct guestfs_aug_ls_ret ret;
2516 };
2517
2518 static void aug_ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2519 {
2520   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2521   struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data;
2522
2523   /* This should definitely not happen. */
2524   if (ctx->cb_sequence != 0) {
2525     ctx->cb_sequence = 9999;
2526     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_ls");
2527     return;
2528   }
2529
2530   ml->main_loop_quit (ml, g);
2531
2532   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2533     error (g, "%s: failed to parse reply header", "guestfs_aug_ls");
2534     return;
2535   }
2536   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2537     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2538       error (g, "%s: failed to parse reply error", "guestfs_aug_ls");
2539       return;
2540     }
2541     goto done;
2542   }
2543   if (!xdr_guestfs_aug_ls_ret (xdr, &ctx->ret)) {
2544     error (g, "%s: failed to parse reply", "guestfs_aug_ls");
2545     return;
2546   }
2547  done:
2548   ctx->cb_sequence = 1;
2549 }
2550
2551 char **guestfs_aug_ls (guestfs_h *g,
2552                 const char *path)
2553 {
2554   struct guestfs_aug_ls_args args;
2555   struct aug_ls_ctx ctx;
2556   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2557   int serial;
2558
2559   if (check_state (g, "guestfs_aug_ls") == -1) return NULL;
2560   guestfs_set_busy (g);
2561
2562   memset (&ctx, 0, sizeof ctx);
2563
2564   args.path = (char *) path;
2565   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LS,
2566         (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
2567   if (serial == -1) {
2568     guestfs_set_ready (g);
2569     return NULL;
2570   }
2571
2572   guestfs__switch_to_receiving (g);
2573   ctx.cb_sequence = 0;
2574   guestfs_set_reply_callback (g, aug_ls_reply_cb, &ctx);
2575   (void) ml->main_loop_run (ml, g);
2576   guestfs_set_reply_callback (g, NULL, NULL);
2577   if (ctx.cb_sequence != 1) {
2578     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls");
2579     guestfs_set_ready (g);
2580     return NULL;
2581   }
2582
2583   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LS, serial) == -1) {
2584     guestfs_set_ready (g);
2585     return NULL;
2586   }
2587
2588   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2589     error (g, "%s", ctx.err.error_message);
2590     guestfs_set_ready (g);
2591     return NULL;
2592   }
2593
2594   guestfs_set_ready (g);
2595   /* caller will free this, but we need to add a NULL entry */
2596   ctx.ret.matches.matches_val =
2597     safe_realloc (g, ctx.ret.matches.matches_val,
2598                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2599   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2600   return ctx.ret.matches.matches_val;
2601 }
2602
2603 struct rm_ctx {
2604   /* This flag is set by the callbacks, so we know we've done
2605    * the callbacks as expected, and in the right sequence.
2606    * 0 = not called, 1 = reply_cb called.
2607    */
2608   int cb_sequence;
2609   struct guestfs_message_header hdr;
2610   struct guestfs_message_error err;
2611 };
2612
2613 static void rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2614 {
2615   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2616   struct rm_ctx *ctx = (struct rm_ctx *) data;
2617
2618   /* This should definitely not happen. */
2619   if (ctx->cb_sequence != 0) {
2620     ctx->cb_sequence = 9999;
2621     error (g, "%s: internal error: reply callback called twice", "guestfs_rm");
2622     return;
2623   }
2624
2625   ml->main_loop_quit (ml, g);
2626
2627   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2628     error (g, "%s: failed to parse reply header", "guestfs_rm");
2629     return;
2630   }
2631   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2632     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2633       error (g, "%s: failed to parse reply error", "guestfs_rm");
2634       return;
2635     }
2636     goto done;
2637   }
2638  done:
2639   ctx->cb_sequence = 1;
2640 }
2641
2642 int guestfs_rm (guestfs_h *g,
2643                 const char *path)
2644 {
2645   struct guestfs_rm_args args;
2646   struct rm_ctx ctx;
2647   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2648   int serial;
2649
2650   if (check_state (g, "guestfs_rm") == -1) return -1;
2651   guestfs_set_busy (g);
2652
2653   memset (&ctx, 0, sizeof ctx);
2654
2655   args.path = (char *) path;
2656   serial = guestfs__send_sync (g, GUESTFS_PROC_RM,
2657         (xdrproc_t) xdr_guestfs_rm_args, (char *) &args);
2658   if (serial == -1) {
2659     guestfs_set_ready (g);
2660     return -1;
2661   }
2662
2663   guestfs__switch_to_receiving (g);
2664   ctx.cb_sequence = 0;
2665   guestfs_set_reply_callback (g, rm_reply_cb, &ctx);
2666   (void) ml->main_loop_run (ml, g);
2667   guestfs_set_reply_callback (g, NULL, NULL);
2668   if (ctx.cb_sequence != 1) {
2669     error (g, "%s reply failed, see earlier error messages", "guestfs_rm");
2670     guestfs_set_ready (g);
2671     return -1;
2672   }
2673
2674   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM, serial) == -1) {
2675     guestfs_set_ready (g);
2676     return -1;
2677   }
2678
2679   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2680     error (g, "%s", ctx.err.error_message);
2681     guestfs_set_ready (g);
2682     return -1;
2683   }
2684
2685   guestfs_set_ready (g);
2686   return 0;
2687 }
2688
2689 struct rmdir_ctx {
2690   /* This flag is set by the callbacks, so we know we've done
2691    * the callbacks as expected, and in the right sequence.
2692    * 0 = not called, 1 = reply_cb called.
2693    */
2694   int cb_sequence;
2695   struct guestfs_message_header hdr;
2696   struct guestfs_message_error err;
2697 };
2698
2699 static void rmdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2700 {
2701   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2702   struct rmdir_ctx *ctx = (struct rmdir_ctx *) data;
2703
2704   /* This should definitely not happen. */
2705   if (ctx->cb_sequence != 0) {
2706     ctx->cb_sequence = 9999;
2707     error (g, "%s: internal error: reply callback called twice", "guestfs_rmdir");
2708     return;
2709   }
2710
2711   ml->main_loop_quit (ml, g);
2712
2713   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2714     error (g, "%s: failed to parse reply header", "guestfs_rmdir");
2715     return;
2716   }
2717   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2718     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2719       error (g, "%s: failed to parse reply error", "guestfs_rmdir");
2720       return;
2721     }
2722     goto done;
2723   }
2724  done:
2725   ctx->cb_sequence = 1;
2726 }
2727
2728 int guestfs_rmdir (guestfs_h *g,
2729                 const char *path)
2730 {
2731   struct guestfs_rmdir_args args;
2732   struct rmdir_ctx ctx;
2733   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2734   int serial;
2735
2736   if (check_state (g, "guestfs_rmdir") == -1) return -1;
2737   guestfs_set_busy (g);
2738
2739   memset (&ctx, 0, sizeof ctx);
2740
2741   args.path = (char *) path;
2742   serial = guestfs__send_sync (g, GUESTFS_PROC_RMDIR,
2743         (xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args);
2744   if (serial == -1) {
2745     guestfs_set_ready (g);
2746     return -1;
2747   }
2748
2749   guestfs__switch_to_receiving (g);
2750   ctx.cb_sequence = 0;
2751   guestfs_set_reply_callback (g, rmdir_reply_cb, &ctx);
2752   (void) ml->main_loop_run (ml, g);
2753   guestfs_set_reply_callback (g, NULL, NULL);
2754   if (ctx.cb_sequence != 1) {
2755     error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir");
2756     guestfs_set_ready (g);
2757     return -1;
2758   }
2759
2760   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RMDIR, serial) == -1) {
2761     guestfs_set_ready (g);
2762     return -1;
2763   }
2764
2765   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2766     error (g, "%s", ctx.err.error_message);
2767     guestfs_set_ready (g);
2768     return -1;
2769   }
2770
2771   guestfs_set_ready (g);
2772   return 0;
2773 }
2774
2775 struct rm_rf_ctx {
2776   /* This flag is set by the callbacks, so we know we've done
2777    * the callbacks as expected, and in the right sequence.
2778    * 0 = not called, 1 = reply_cb called.
2779    */
2780   int cb_sequence;
2781   struct guestfs_message_header hdr;
2782   struct guestfs_message_error err;
2783 };
2784
2785 static void rm_rf_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2786 {
2787   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2788   struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data;
2789
2790   /* This should definitely not happen. */
2791   if (ctx->cb_sequence != 0) {
2792     ctx->cb_sequence = 9999;
2793     error (g, "%s: internal error: reply callback called twice", "guestfs_rm_rf");
2794     return;
2795   }
2796
2797   ml->main_loop_quit (ml, g);
2798
2799   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2800     error (g, "%s: failed to parse reply header", "guestfs_rm_rf");
2801     return;
2802   }
2803   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2804     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2805       error (g, "%s: failed to parse reply error", "guestfs_rm_rf");
2806       return;
2807     }
2808     goto done;
2809   }
2810  done:
2811   ctx->cb_sequence = 1;
2812 }
2813
2814 int guestfs_rm_rf (guestfs_h *g,
2815                 const char *path)
2816 {
2817   struct guestfs_rm_rf_args args;
2818   struct rm_rf_ctx ctx;
2819   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2820   int serial;
2821
2822   if (check_state (g, "guestfs_rm_rf") == -1) return -1;
2823   guestfs_set_busy (g);
2824
2825   memset (&ctx, 0, sizeof ctx);
2826
2827   args.path = (char *) path;
2828   serial = guestfs__send_sync (g, GUESTFS_PROC_RM_RF,
2829         (xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args);
2830   if (serial == -1) {
2831     guestfs_set_ready (g);
2832     return -1;
2833   }
2834
2835   guestfs__switch_to_receiving (g);
2836   ctx.cb_sequence = 0;
2837   guestfs_set_reply_callback (g, rm_rf_reply_cb, &ctx);
2838   (void) ml->main_loop_run (ml, g);
2839   guestfs_set_reply_callback (g, NULL, NULL);
2840   if (ctx.cb_sequence != 1) {
2841     error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf");
2842     guestfs_set_ready (g);
2843     return -1;
2844   }
2845
2846   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM_RF, serial) == -1) {
2847     guestfs_set_ready (g);
2848     return -1;
2849   }
2850
2851   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2852     error (g, "%s", ctx.err.error_message);
2853     guestfs_set_ready (g);
2854     return -1;
2855   }
2856
2857   guestfs_set_ready (g);
2858   return 0;
2859 }
2860
2861 struct mkdir_ctx {
2862   /* This flag is set by the callbacks, so we know we've done
2863    * the callbacks as expected, and in the right sequence.
2864    * 0 = not called, 1 = reply_cb called.
2865    */
2866   int cb_sequence;
2867   struct guestfs_message_header hdr;
2868   struct guestfs_message_error err;
2869 };
2870
2871 static void mkdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2872 {
2873   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2874   struct mkdir_ctx *ctx = (struct mkdir_ctx *) data;
2875
2876   /* This should definitely not happen. */
2877   if (ctx->cb_sequence != 0) {
2878     ctx->cb_sequence = 9999;
2879     error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir");
2880     return;
2881   }
2882
2883   ml->main_loop_quit (ml, g);
2884
2885   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2886     error (g, "%s: failed to parse reply header", "guestfs_mkdir");
2887     return;
2888   }
2889   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2890     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2891       error (g, "%s: failed to parse reply error", "guestfs_mkdir");
2892       return;
2893     }
2894     goto done;
2895   }
2896  done:
2897   ctx->cb_sequence = 1;
2898 }
2899
2900 int guestfs_mkdir (guestfs_h *g,
2901                 const char *path)
2902 {
2903   struct guestfs_mkdir_args args;
2904   struct mkdir_ctx ctx;
2905   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2906   int serial;
2907
2908   if (check_state (g, "guestfs_mkdir") == -1) return -1;
2909   guestfs_set_busy (g);
2910
2911   memset (&ctx, 0, sizeof ctx);
2912
2913   args.path = (char *) path;
2914   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR,
2915         (xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args);
2916   if (serial == -1) {
2917     guestfs_set_ready (g);
2918     return -1;
2919   }
2920
2921   guestfs__switch_to_receiving (g);
2922   ctx.cb_sequence = 0;
2923   guestfs_set_reply_callback (g, mkdir_reply_cb, &ctx);
2924   (void) ml->main_loop_run (ml, g);
2925   guestfs_set_reply_callback (g, NULL, NULL);
2926   if (ctx.cb_sequence != 1) {
2927     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir");
2928     guestfs_set_ready (g);
2929     return -1;
2930   }
2931
2932   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR, serial) == -1) {
2933     guestfs_set_ready (g);
2934     return -1;
2935   }
2936
2937   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2938     error (g, "%s", ctx.err.error_message);
2939     guestfs_set_ready (g);
2940     return -1;
2941   }
2942
2943   guestfs_set_ready (g);
2944   return 0;
2945 }
2946
2947 struct mkdir_p_ctx {
2948   /* This flag is set by the callbacks, so we know we've done
2949    * the callbacks as expected, and in the right sequence.
2950    * 0 = not called, 1 = reply_cb called.
2951    */
2952   int cb_sequence;
2953   struct guestfs_message_header hdr;
2954   struct guestfs_message_error err;
2955 };
2956
2957 static void mkdir_p_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2958 {
2959   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2960   struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data;
2961
2962   /* This should definitely not happen. */
2963   if (ctx->cb_sequence != 0) {
2964     ctx->cb_sequence = 9999;
2965     error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir_p");
2966     return;
2967   }
2968
2969   ml->main_loop_quit (ml, g);
2970
2971   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2972     error (g, "%s: failed to parse reply header", "guestfs_mkdir_p");
2973     return;
2974   }
2975   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2976     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2977       error (g, "%s: failed to parse reply error", "guestfs_mkdir_p");
2978       return;
2979     }
2980     goto done;
2981   }
2982  done:
2983   ctx->cb_sequence = 1;
2984 }
2985
2986 int guestfs_mkdir_p (guestfs_h *g,
2987                 const char *path)
2988 {
2989   struct guestfs_mkdir_p_args args;
2990   struct mkdir_p_ctx ctx;
2991   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2992   int serial;
2993
2994   if (check_state (g, "guestfs_mkdir_p") == -1) return -1;
2995   guestfs_set_busy (g);
2996
2997   memset (&ctx, 0, sizeof ctx);
2998
2999   args.path = (char *) path;
3000   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR_P,
3001         (xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args);
3002   if (serial == -1) {
3003     guestfs_set_ready (g);
3004     return -1;
3005   }
3006
3007   guestfs__switch_to_receiving (g);
3008   ctx.cb_sequence = 0;
3009   guestfs_set_reply_callback (g, mkdir_p_reply_cb, &ctx);
3010   (void) ml->main_loop_run (ml, g);
3011   guestfs_set_reply_callback (g, NULL, NULL);
3012   if (ctx.cb_sequence != 1) {
3013     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p");
3014     guestfs_set_ready (g);
3015     return -1;
3016   }
3017
3018   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1) {
3019     guestfs_set_ready (g);
3020     return -1;
3021   }
3022
3023   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3024     error (g, "%s", ctx.err.error_message);
3025     guestfs_set_ready (g);
3026     return -1;
3027   }
3028
3029   guestfs_set_ready (g);
3030   return 0;
3031 }
3032
3033 struct chmod_ctx {
3034   /* This flag is set by the callbacks, so we know we've done
3035    * the callbacks as expected, and in the right sequence.
3036    * 0 = not called, 1 = reply_cb called.
3037    */
3038   int cb_sequence;
3039   struct guestfs_message_header hdr;
3040   struct guestfs_message_error err;
3041 };
3042
3043 static void chmod_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3044 {
3045   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3046   struct chmod_ctx *ctx = (struct chmod_ctx *) data;
3047
3048   /* This should definitely not happen. */
3049   if (ctx->cb_sequence != 0) {
3050     ctx->cb_sequence = 9999;
3051     error (g, "%s: internal error: reply callback called twice", "guestfs_chmod");
3052     return;
3053   }
3054
3055   ml->main_loop_quit (ml, g);
3056
3057   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3058     error (g, "%s: failed to parse reply header", "guestfs_chmod");
3059     return;
3060   }
3061   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3062     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3063       error (g, "%s: failed to parse reply error", "guestfs_chmod");
3064       return;
3065     }
3066     goto done;
3067   }
3068  done:
3069   ctx->cb_sequence = 1;
3070 }
3071
3072 int guestfs_chmod (guestfs_h *g,
3073                 int mode,
3074                 const char *path)
3075 {
3076   struct guestfs_chmod_args args;
3077   struct chmod_ctx ctx;
3078   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3079   int serial;
3080
3081   if (check_state (g, "guestfs_chmod") == -1) return -1;
3082   guestfs_set_busy (g);
3083
3084   memset (&ctx, 0, sizeof ctx);
3085
3086   args.mode = mode;
3087   args.path = (char *) path;
3088   serial = guestfs__send_sync (g, GUESTFS_PROC_CHMOD,
3089         (xdrproc_t) xdr_guestfs_chmod_args, (char *) &args);
3090   if (serial == -1) {
3091     guestfs_set_ready (g);
3092     return -1;
3093   }
3094
3095   guestfs__switch_to_receiving (g);
3096   ctx.cb_sequence = 0;
3097   guestfs_set_reply_callback (g, chmod_reply_cb, &ctx);
3098   (void) ml->main_loop_run (ml, g);
3099   guestfs_set_reply_callback (g, NULL, NULL);
3100   if (ctx.cb_sequence != 1) {
3101     error (g, "%s reply failed, see earlier error messages", "guestfs_chmod");
3102     guestfs_set_ready (g);
3103     return -1;
3104   }
3105
3106   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHMOD, serial) == -1) {
3107     guestfs_set_ready (g);
3108     return -1;
3109   }
3110
3111   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3112     error (g, "%s", ctx.err.error_message);
3113     guestfs_set_ready (g);
3114     return -1;
3115   }
3116
3117   guestfs_set_ready (g);
3118   return 0;
3119 }
3120
3121 struct chown_ctx {
3122   /* This flag is set by the callbacks, so we know we've done
3123    * the callbacks as expected, and in the right sequence.
3124    * 0 = not called, 1 = reply_cb called.
3125    */
3126   int cb_sequence;
3127   struct guestfs_message_header hdr;
3128   struct guestfs_message_error err;
3129 };
3130
3131 static void chown_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3132 {
3133   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3134   struct chown_ctx *ctx = (struct chown_ctx *) data;
3135
3136   /* This should definitely not happen. */
3137   if (ctx->cb_sequence != 0) {
3138     ctx->cb_sequence = 9999;
3139     error (g, "%s: internal error: reply callback called twice", "guestfs_chown");
3140     return;
3141   }
3142
3143   ml->main_loop_quit (ml, g);
3144
3145   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3146     error (g, "%s: failed to parse reply header", "guestfs_chown");
3147     return;
3148   }
3149   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3150     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3151       error (g, "%s: failed to parse reply error", "guestfs_chown");
3152       return;
3153     }
3154     goto done;
3155   }
3156  done:
3157   ctx->cb_sequence = 1;
3158 }
3159
3160 int guestfs_chown (guestfs_h *g,
3161                 int owner,
3162                 int group,
3163                 const char *path)
3164 {
3165   struct guestfs_chown_args args;
3166   struct chown_ctx ctx;
3167   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3168   int serial;
3169
3170   if (check_state (g, "guestfs_chown") == -1) return -1;
3171   guestfs_set_busy (g);
3172
3173   memset (&ctx, 0, sizeof ctx);
3174
3175   args.owner = owner;
3176   args.group = group;
3177   args.path = (char *) path;
3178   serial = guestfs__send_sync (g, GUESTFS_PROC_CHOWN,
3179         (xdrproc_t) xdr_guestfs_chown_args, (char *) &args);
3180   if (serial == -1) {
3181     guestfs_set_ready (g);
3182     return -1;
3183   }
3184
3185   guestfs__switch_to_receiving (g);
3186   ctx.cb_sequence = 0;
3187   guestfs_set_reply_callback (g, chown_reply_cb, &ctx);
3188   (void) ml->main_loop_run (ml, g);
3189   guestfs_set_reply_callback (g, NULL, NULL);
3190   if (ctx.cb_sequence != 1) {
3191     error (g, "%s reply failed, see earlier error messages", "guestfs_chown");
3192     guestfs_set_ready (g);
3193     return -1;
3194   }
3195
3196   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHOWN, serial) == -1) {
3197     guestfs_set_ready (g);
3198     return -1;
3199   }
3200
3201   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3202     error (g, "%s", ctx.err.error_message);
3203     guestfs_set_ready (g);
3204     return -1;
3205   }
3206
3207   guestfs_set_ready (g);
3208   return 0;
3209 }
3210
3211 struct exists_ctx {
3212   /* This flag is set by the callbacks, so we know we've done
3213    * the callbacks as expected, and in the right sequence.
3214    * 0 = not called, 1 = reply_cb called.
3215    */
3216   int cb_sequence;
3217   struct guestfs_message_header hdr;
3218   struct guestfs_message_error err;
3219   struct guestfs_exists_ret ret;
3220 };
3221
3222 static void exists_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3223 {
3224   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3225   struct exists_ctx *ctx = (struct exists_ctx *) data;
3226
3227   /* This should definitely not happen. */
3228   if (ctx->cb_sequence != 0) {
3229     ctx->cb_sequence = 9999;
3230     error (g, "%s: internal error: reply callback called twice", "guestfs_exists");
3231     return;
3232   }
3233
3234   ml->main_loop_quit (ml, g);
3235
3236   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3237     error (g, "%s: failed to parse reply header", "guestfs_exists");
3238     return;
3239   }
3240   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3241     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3242       error (g, "%s: failed to parse reply error", "guestfs_exists");
3243       return;
3244     }
3245     goto done;
3246   }
3247   if (!xdr_guestfs_exists_ret (xdr, &ctx->ret)) {
3248     error (g, "%s: failed to parse reply", "guestfs_exists");
3249     return;
3250   }
3251  done:
3252   ctx->cb_sequence = 1;
3253 }
3254
3255 int guestfs_exists (guestfs_h *g,
3256                 const char *path)
3257 {
3258   struct guestfs_exists_args args;
3259   struct exists_ctx ctx;
3260   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3261   int serial;
3262
3263   if (check_state (g, "guestfs_exists") == -1) return -1;
3264   guestfs_set_busy (g);
3265
3266   memset (&ctx, 0, sizeof ctx);
3267
3268   args.path = (char *) path;
3269   serial = guestfs__send_sync (g, GUESTFS_PROC_EXISTS,
3270         (xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
3271   if (serial == -1) {
3272     guestfs_set_ready (g);
3273     return -1;
3274   }
3275
3276   guestfs__switch_to_receiving (g);
3277   ctx.cb_sequence = 0;
3278   guestfs_set_reply_callback (g, exists_reply_cb, &ctx);
3279   (void) ml->main_loop_run (ml, g);
3280   guestfs_set_reply_callback (g, NULL, NULL);
3281   if (ctx.cb_sequence != 1) {
3282     error (g, "%s reply failed, see earlier error messages", "guestfs_exists");
3283     guestfs_set_ready (g);
3284     return -1;
3285   }
3286
3287   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EXISTS, serial) == -1) {
3288     guestfs_set_ready (g);
3289     return -1;
3290   }
3291
3292   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3293     error (g, "%s", ctx.err.error_message);
3294     guestfs_set_ready (g);
3295     return -1;
3296   }
3297
3298   guestfs_set_ready (g);
3299   return ctx.ret.existsflag;
3300 }
3301
3302 struct is_file_ctx {
3303   /* This flag is set by the callbacks, so we know we've done
3304    * the callbacks as expected, and in the right sequence.
3305    * 0 = not called, 1 = reply_cb called.
3306    */
3307   int cb_sequence;
3308   struct guestfs_message_header hdr;
3309   struct guestfs_message_error err;
3310   struct guestfs_is_file_ret ret;
3311 };
3312
3313 static void is_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3314 {
3315   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3316   struct is_file_ctx *ctx = (struct is_file_ctx *) data;
3317
3318   /* This should definitely not happen. */
3319   if (ctx->cb_sequence != 0) {
3320     ctx->cb_sequence = 9999;
3321     error (g, "%s: internal error: reply callback called twice", "guestfs_is_file");
3322     return;
3323   }
3324
3325   ml->main_loop_quit (ml, g);
3326
3327   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3328     error (g, "%s: failed to parse reply header", "guestfs_is_file");
3329     return;
3330   }
3331   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3332     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3333       error (g, "%s: failed to parse reply error", "guestfs_is_file");
3334       return;
3335     }
3336     goto done;
3337   }
3338   if (!xdr_guestfs_is_file_ret (xdr, &ctx->ret)) {
3339     error (g, "%s: failed to parse reply", "guestfs_is_file");
3340     return;
3341   }
3342  done:
3343   ctx->cb_sequence = 1;
3344 }
3345
3346 int guestfs_is_file (guestfs_h *g,
3347                 const char *path)
3348 {
3349   struct guestfs_is_file_args args;
3350   struct is_file_ctx ctx;
3351   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3352   int serial;
3353
3354   if (check_state (g, "guestfs_is_file") == -1) return -1;
3355   guestfs_set_busy (g);
3356
3357   memset (&ctx, 0, sizeof ctx);
3358
3359   args.path = (char *) path;
3360   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_FILE,
3361         (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
3362   if (serial == -1) {
3363     guestfs_set_ready (g);
3364     return -1;
3365   }
3366
3367   guestfs__switch_to_receiving (g);
3368   ctx.cb_sequence = 0;
3369   guestfs_set_reply_callback (g, is_file_reply_cb, &ctx);
3370   (void) ml->main_loop_run (ml, g);
3371   guestfs_set_reply_callback (g, NULL, NULL);
3372   if (ctx.cb_sequence != 1) {
3373     error (g, "%s reply failed, see earlier error messages", "guestfs_is_file");
3374     guestfs_set_ready (g);
3375     return -1;
3376   }
3377
3378   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_FILE, serial) == -1) {
3379     guestfs_set_ready (g);
3380     return -1;
3381   }
3382
3383   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3384     error (g, "%s", ctx.err.error_message);
3385     guestfs_set_ready (g);
3386     return -1;
3387   }
3388
3389   guestfs_set_ready (g);
3390   return ctx.ret.fileflag;
3391 }
3392
3393 struct is_dir_ctx {
3394   /* This flag is set by the callbacks, so we know we've done
3395    * the callbacks as expected, and in the right sequence.
3396    * 0 = not called, 1 = reply_cb called.
3397    */
3398   int cb_sequence;
3399   struct guestfs_message_header hdr;
3400   struct guestfs_message_error err;
3401   struct guestfs_is_dir_ret ret;
3402 };
3403
3404 static void is_dir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3405 {
3406   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3407   struct is_dir_ctx *ctx = (struct is_dir_ctx *) data;
3408
3409   /* This should definitely not happen. */
3410   if (ctx->cb_sequence != 0) {
3411     ctx->cb_sequence = 9999;
3412     error (g, "%s: internal error: reply callback called twice", "guestfs_is_dir");
3413     return;
3414   }
3415
3416   ml->main_loop_quit (ml, g);
3417
3418   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3419     error (g, "%s: failed to parse reply header", "guestfs_is_dir");
3420     return;
3421   }
3422   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3423     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3424       error (g, "%s: failed to parse reply error", "guestfs_is_dir");
3425       return;
3426     }
3427     goto done;
3428   }
3429   if (!xdr_guestfs_is_dir_ret (xdr, &ctx->ret)) {
3430     error (g, "%s: failed to parse reply", "guestfs_is_dir");
3431     return;
3432   }
3433  done:
3434   ctx->cb_sequence = 1;
3435 }
3436
3437 int guestfs_is_dir (guestfs_h *g,
3438                 const char *path)
3439 {
3440   struct guestfs_is_dir_args args;
3441   struct is_dir_ctx ctx;
3442   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3443   int serial;
3444
3445   if (check_state (g, "guestfs_is_dir") == -1) return -1;
3446   guestfs_set_busy (g);
3447
3448   memset (&ctx, 0, sizeof ctx);
3449
3450   args.path = (char *) path;
3451   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_DIR,
3452         (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
3453   if (serial == -1) {
3454     guestfs_set_ready (g);
3455     return -1;
3456   }
3457
3458   guestfs__switch_to_receiving (g);
3459   ctx.cb_sequence = 0;
3460   guestfs_set_reply_callback (g, is_dir_reply_cb, &ctx);
3461   (void) ml->main_loop_run (ml, g);
3462   guestfs_set_reply_callback (g, NULL, NULL);
3463   if (ctx.cb_sequence != 1) {
3464     error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir");
3465     guestfs_set_ready (g);
3466     return -1;
3467   }
3468
3469   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_DIR, serial) == -1) {
3470     guestfs_set_ready (g);
3471     return -1;
3472   }
3473
3474   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3475     error (g, "%s", ctx.err.error_message);
3476     guestfs_set_ready (g);
3477     return -1;
3478   }
3479
3480   guestfs_set_ready (g);
3481   return ctx.ret.dirflag;
3482 }
3483
3484 struct pvcreate_ctx {
3485   /* This flag is set by the callbacks, so we know we've done
3486    * the callbacks as expected, and in the right sequence.
3487    * 0 = not called, 1 = reply_cb called.
3488    */
3489   int cb_sequence;
3490   struct guestfs_message_header hdr;
3491   struct guestfs_message_error err;
3492 };
3493
3494 static void pvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3495 {
3496   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3497   struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data;
3498
3499   /* This should definitely not happen. */
3500   if (ctx->cb_sequence != 0) {
3501     ctx->cb_sequence = 9999;
3502     error (g, "%s: internal error: reply callback called twice", "guestfs_pvcreate");
3503     return;
3504   }
3505
3506   ml->main_loop_quit (ml, g);
3507
3508   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3509     error (g, "%s: failed to parse reply header", "guestfs_pvcreate");
3510     return;
3511   }
3512   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3513     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3514       error (g, "%s: failed to parse reply error", "guestfs_pvcreate");
3515       return;
3516     }
3517     goto done;
3518   }
3519  done:
3520   ctx->cb_sequence = 1;
3521 }
3522
3523 int guestfs_pvcreate (guestfs_h *g,
3524                 const char *device)
3525 {
3526   struct guestfs_pvcreate_args args;
3527   struct pvcreate_ctx ctx;
3528   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3529   int serial;
3530
3531   if (check_state (g, "guestfs_pvcreate") == -1) return -1;
3532   guestfs_set_busy (g);
3533
3534   memset (&ctx, 0, sizeof ctx);
3535
3536   args.device = (char *) device;
3537   serial = guestfs__send_sync (g, GUESTFS_PROC_PVCREATE,
3538         (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
3539   if (serial == -1) {
3540     guestfs_set_ready (g);
3541     return -1;
3542   }
3543
3544   guestfs__switch_to_receiving (g);
3545   ctx.cb_sequence = 0;
3546   guestfs_set_reply_callback (g, pvcreate_reply_cb, &ctx);
3547   (void) ml->main_loop_run (ml, g);
3548   guestfs_set_reply_callback (g, NULL, NULL);
3549   if (ctx.cb_sequence != 1) {
3550     error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate");
3551     guestfs_set_ready (g);
3552     return -1;
3553   }
3554
3555   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVCREATE, serial) == -1) {
3556     guestfs_set_ready (g);
3557     return -1;
3558   }
3559
3560   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3561     error (g, "%s", ctx.err.error_message);
3562     guestfs_set_ready (g);
3563     return -1;
3564   }
3565
3566   guestfs_set_ready (g);
3567   return 0;
3568 }
3569
3570 struct vgcreate_ctx {
3571   /* This flag is set by the callbacks, so we know we've done
3572    * the callbacks as expected, and in the right sequence.
3573    * 0 = not called, 1 = reply_cb called.
3574    */
3575   int cb_sequence;
3576   struct guestfs_message_header hdr;
3577   struct guestfs_message_error err;
3578 };
3579
3580 static void vgcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3581 {
3582   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3583   struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data;
3584
3585   /* This should definitely not happen. */
3586   if (ctx->cb_sequence != 0) {
3587     ctx->cb_sequence = 9999;
3588     error (g, "%s: internal error: reply callback called twice", "guestfs_vgcreate");
3589     return;
3590   }
3591
3592   ml->main_loop_quit (ml, g);
3593
3594   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3595     error (g, "%s: failed to parse reply header", "guestfs_vgcreate");
3596     return;
3597   }
3598   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3599     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3600       error (g, "%s: failed to parse reply error", "guestfs_vgcreate");
3601       return;
3602     }
3603     goto done;
3604   }
3605  done:
3606   ctx->cb_sequence = 1;
3607 }
3608
3609 int guestfs_vgcreate (guestfs_h *g,
3610                 const char *volgroup,
3611                 char * const* const physvols)
3612 {
3613   struct guestfs_vgcreate_args args;
3614   struct vgcreate_ctx ctx;
3615   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3616   int serial;
3617
3618   if (check_state (g, "guestfs_vgcreate") == -1) return -1;
3619   guestfs_set_busy (g);
3620
3621   memset (&ctx, 0, sizeof ctx);
3622
3623   args.volgroup = (char *) volgroup;
3624   args.physvols.physvols_val = (char **) physvols;
3625   for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ;
3626   serial = guestfs__send_sync (g, GUESTFS_PROC_VGCREATE,
3627         (xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
3628   if (serial == -1) {
3629     guestfs_set_ready (g);
3630     return -1;
3631   }
3632
3633   guestfs__switch_to_receiving (g);
3634   ctx.cb_sequence = 0;
3635   guestfs_set_reply_callback (g, vgcreate_reply_cb, &ctx);
3636   (void) ml->main_loop_run (ml, g);
3637   guestfs_set_reply_callback (g, NULL, NULL);
3638   if (ctx.cb_sequence != 1) {
3639     error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate");
3640     guestfs_set_ready (g);
3641     return -1;
3642   }
3643
3644   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGCREATE, serial) == -1) {
3645     guestfs_set_ready (g);
3646     return -1;
3647   }
3648
3649   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3650     error (g, "%s", ctx.err.error_message);
3651     guestfs_set_ready (g);
3652     return -1;
3653   }
3654
3655   guestfs_set_ready (g);
3656   return 0;
3657 }
3658
3659 struct lvcreate_ctx {
3660   /* This flag is set by the callbacks, so we know we've done
3661    * the callbacks as expected, and in the right sequence.
3662    * 0 = not called, 1 = reply_cb called.
3663    */
3664   int cb_sequence;
3665   struct guestfs_message_header hdr;
3666   struct guestfs_message_error err;
3667 };
3668
3669 static void lvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3670 {
3671   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3672   struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data;
3673
3674   /* This should definitely not happen. */
3675   if (ctx->cb_sequence != 0) {
3676     ctx->cb_sequence = 9999;
3677     error (g, "%s: internal error: reply callback called twice", "guestfs_lvcreate");
3678     return;
3679   }
3680
3681   ml->main_loop_quit (ml, g);
3682
3683   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3684     error (g, "%s: failed to parse reply header", "guestfs_lvcreate");
3685     return;
3686   }
3687   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3688     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3689       error (g, "%s: failed to parse reply error", "guestfs_lvcreate");
3690       return;
3691     }
3692     goto done;
3693   }
3694  done:
3695   ctx->cb_sequence = 1;
3696 }
3697
3698 int guestfs_lvcreate (guestfs_h *g,
3699                 const char *logvol,
3700                 const char *volgroup,
3701                 int mbytes)
3702 {
3703   struct guestfs_lvcreate_args args;
3704   struct lvcreate_ctx ctx;
3705   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3706   int serial;
3707
3708   if (check_state (g, "guestfs_lvcreate") == -1) return -1;
3709   guestfs_set_busy (g);
3710
3711   memset (&ctx, 0, sizeof ctx);
3712
3713   args.logvol = (char *) logvol;
3714   args.volgroup = (char *) volgroup;
3715   args.mbytes = mbytes;
3716   serial = guestfs__send_sync (g, GUESTFS_PROC_LVCREATE,
3717         (xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
3718   if (serial == -1) {
3719     guestfs_set_ready (g);
3720     return -1;
3721   }
3722
3723   guestfs__switch_to_receiving (g);
3724   ctx.cb_sequence = 0;
3725   guestfs_set_reply_callback (g, lvcreate_reply_cb, &ctx);
3726   (void) ml->main_loop_run (ml, g);
3727   guestfs_set_reply_callback (g, NULL, NULL);
3728   if (ctx.cb_sequence != 1) {
3729     error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate");
3730     guestfs_set_ready (g);
3731     return -1;
3732   }
3733
3734   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVCREATE, serial) == -1) {
3735     guestfs_set_ready (g);
3736     return -1;
3737   }
3738
3739   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3740     error (g, "%s", ctx.err.error_message);
3741     guestfs_set_ready (g);
3742     return -1;
3743   }
3744
3745   guestfs_set_ready (g);
3746   return 0;
3747 }
3748
3749 struct mkfs_ctx {
3750   /* This flag is set by the callbacks, so we know we've done
3751    * the callbacks as expected, and in the right sequence.
3752    * 0 = not called, 1 = reply_cb called.
3753    */
3754   int cb_sequence;
3755   struct guestfs_message_header hdr;
3756   struct guestfs_message_error err;
3757 };
3758
3759 static void mkfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3760 {
3761   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3762   struct mkfs_ctx *ctx = (struct mkfs_ctx *) data;
3763
3764   /* This should definitely not happen. */
3765   if (ctx->cb_sequence != 0) {
3766     ctx->cb_sequence = 9999;
3767     error (g, "%s: internal error: reply callback called twice", "guestfs_mkfs");
3768     return;
3769   }
3770
3771   ml->main_loop_quit (ml, g);
3772
3773   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3774     error (g, "%s: failed to parse reply header", "guestfs_mkfs");
3775     return;
3776   }
3777   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3778     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3779       error (g, "%s: failed to parse reply error", "guestfs_mkfs");
3780       return;
3781     }
3782     goto done;
3783   }
3784  done:
3785   ctx->cb_sequence = 1;
3786 }
3787
3788 int guestfs_mkfs (guestfs_h *g,
3789                 const char *fstype,
3790                 const char *device)
3791 {
3792   struct guestfs_mkfs_args args;
3793   struct mkfs_ctx ctx;
3794   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3795   int serial;
3796
3797   if (check_state (g, "guestfs_mkfs") == -1) return -1;
3798   guestfs_set_busy (g);
3799
3800   memset (&ctx, 0, sizeof ctx);
3801
3802   args.fstype = (char *) fstype;
3803   args.device = (char *) device;
3804   serial = guestfs__send_sync (g, GUESTFS_PROC_MKFS,
3805         (xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
3806   if (serial == -1) {
3807     guestfs_set_ready (g);
3808     return -1;
3809   }
3810
3811   guestfs__switch_to_receiving (g);
3812   ctx.cb_sequence = 0;
3813   guestfs_set_reply_callback (g, mkfs_reply_cb, &ctx);
3814   (void) ml->main_loop_run (ml, g);
3815   guestfs_set_reply_callback (g, NULL, NULL);
3816   if (ctx.cb_sequence != 1) {
3817     error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs");
3818     guestfs_set_ready (g);
3819     return -1;
3820   }
3821
3822   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFS, serial) == -1) {
3823     guestfs_set_ready (g);
3824     return -1;
3825   }
3826
3827   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3828     error (g, "%s", ctx.err.error_message);
3829     guestfs_set_ready (g);
3830     return -1;
3831   }
3832
3833   guestfs_set_ready (g);
3834   return 0;
3835 }
3836
3837 struct sfdisk_ctx {
3838   /* This flag is set by the callbacks, so we know we've done
3839    * the callbacks as expected, and in the right sequence.
3840    * 0 = not called, 1 = reply_cb called.
3841    */
3842   int cb_sequence;
3843   struct guestfs_message_header hdr;
3844   struct guestfs_message_error err;
3845 };
3846
3847 static void sfdisk_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3848 {
3849   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3850   struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data;
3851
3852   /* This should definitely not happen. */
3853   if (ctx->cb_sequence != 0) {
3854     ctx->cb_sequence = 9999;
3855     error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk");
3856     return;
3857   }
3858
3859   ml->main_loop_quit (ml, g);
3860
3861   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3862     error (g, "%s: failed to parse reply header", "guestfs_sfdisk");
3863     return;
3864   }
3865   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3866     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3867       error (g, "%s: failed to parse reply error", "guestfs_sfdisk");
3868       return;
3869     }
3870     goto done;
3871   }
3872  done:
3873   ctx->cb_sequence = 1;
3874 }
3875
3876 int guestfs_sfdisk (guestfs_h *g,
3877                 const char *device,
3878                 int cyls,
3879                 int heads,
3880                 int sectors,
3881                 char * const* const lines)
3882 {
3883   struct guestfs_sfdisk_args args;
3884   struct sfdisk_ctx ctx;
3885   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3886   int serial;
3887
3888   if (check_state (g, "guestfs_sfdisk") == -1) return -1;
3889   guestfs_set_busy (g);
3890
3891   memset (&ctx, 0, sizeof ctx);
3892
3893   args.device = (char *) device;
3894   args.cyls = cyls;
3895   args.heads = heads;
3896   args.sectors = sectors;
3897   args.lines.lines_val = (char **) lines;
3898   for (args.lines.lines_len = 0; lines[args.lines.lines_len]; args.lines.lines_len++) ;
3899   serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK,
3900         (xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
3901   if (serial == -1) {
3902     guestfs_set_ready (g);
3903     return -1;
3904   }
3905
3906   guestfs__switch_to_receiving (g);
3907   ctx.cb_sequence = 0;
3908   guestfs_set_reply_callback (g, sfdisk_reply_cb, &ctx);
3909   (void) ml->main_loop_run (ml, g);
3910   guestfs_set_reply_callback (g, NULL, NULL);
3911   if (ctx.cb_sequence != 1) {
3912     error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk");
3913     guestfs_set_ready (g);
3914     return -1;
3915   }
3916
3917   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK, serial) == -1) {
3918     guestfs_set_ready (g);
3919     return -1;
3920   }
3921
3922   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3923     error (g, "%s", ctx.err.error_message);
3924     guestfs_set_ready (g);
3925     return -1;
3926   }
3927
3928   guestfs_set_ready (g);
3929   return 0;
3930 }
3931
3932 struct write_file_ctx {
3933   /* This flag is set by the callbacks, so we know we've done
3934    * the callbacks as expected, and in the right sequence.
3935    * 0 = not called, 1 = reply_cb called.
3936    */
3937   int cb_sequence;
3938   struct guestfs_message_header hdr;
3939   struct guestfs_message_error err;
3940 };
3941
3942 static void write_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3943 {
3944   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3945   struct write_file_ctx *ctx = (struct write_file_ctx *) data;
3946
3947   /* This should definitely not happen. */
3948   if (ctx->cb_sequence != 0) {
3949     ctx->cb_sequence = 9999;
3950     error (g, "%s: internal error: reply callback called twice", "guestfs_write_file");
3951     return;
3952   }
3953
3954   ml->main_loop_quit (ml, g);
3955
3956   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3957     error (g, "%s: failed to parse reply header", "guestfs_write_file");
3958     return;
3959   }
3960   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3961     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3962       error (g, "%s: failed to parse reply error", "guestfs_write_file");
3963       return;
3964     }
3965     goto done;
3966   }
3967  done:
3968   ctx->cb_sequence = 1;
3969 }
3970
3971 int guestfs_write_file (guestfs_h *g,
3972                 const char *path,
3973                 const char *content,
3974                 int size)
3975 {
3976   struct guestfs_write_file_args args;
3977   struct write_file_ctx ctx;
3978   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3979   int serial;
3980
3981   if (check_state (g, "guestfs_write_file") == -1) return -1;
3982   guestfs_set_busy (g);
3983
3984   memset (&ctx, 0, sizeof ctx);
3985
3986   args.path = (char *) path;
3987   args.content = (char *) content;
3988   args.size = size;
3989   serial = guestfs__send_sync (g, GUESTFS_PROC_WRITE_FILE,
3990         (xdrproc_t) xdr_guestfs_write_file_args, (char *) &args);
3991   if (serial == -1) {
3992     guestfs_set_ready (g);
3993     return -1;
3994   }
3995
3996   guestfs__switch_to_receiving (g);
3997   ctx.cb_sequence = 0;
3998   guestfs_set_reply_callback (g, write_file_reply_cb, &ctx);
3999   (void) ml->main_loop_run (ml, g);
4000   guestfs_set_reply_callback (g, NULL, NULL);
4001   if (ctx.cb_sequence != 1) {
4002     error (g, "%s reply failed, see earlier error messages", "guestfs_write_file");
4003     guestfs_set_ready (g);
4004     return -1;
4005   }
4006
4007   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1) {
4008     guestfs_set_ready (g);
4009     return -1;
4010   }
4011
4012   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4013     error (g, "%s", ctx.err.error_message);
4014     guestfs_set_ready (g);
4015     return -1;
4016   }
4017
4018   guestfs_set_ready (g);
4019   return 0;
4020 }
4021
4022 struct umount_ctx {
4023   /* This flag is set by the callbacks, so we know we've done
4024    * the callbacks as expected, and in the right sequence.
4025    * 0 = not called, 1 = reply_cb called.
4026    */
4027   int cb_sequence;
4028   struct guestfs_message_header hdr;
4029   struct guestfs_message_error err;
4030 };
4031
4032 static void umount_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4033 {
4034   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4035   struct umount_ctx *ctx = (struct umount_ctx *) data;
4036
4037   /* This should definitely not happen. */
4038   if (ctx->cb_sequence != 0) {
4039     ctx->cb_sequence = 9999;
4040     error (g, "%s: internal error: reply callback called twice", "guestfs_umount");
4041     return;
4042   }
4043
4044   ml->main_loop_quit (ml, g);
4045
4046   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4047     error (g, "%s: failed to parse reply header", "guestfs_umount");
4048     return;
4049   }
4050   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4051     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4052       error (g, "%s: failed to parse reply error", "guestfs_umount");
4053       return;
4054     }
4055     goto done;
4056   }
4057  done:
4058   ctx->cb_sequence = 1;
4059 }
4060
4061 int guestfs_umount (guestfs_h *g,
4062                 const char *pathordevice)
4063 {
4064   struct guestfs_umount_args args;
4065   struct umount_ctx ctx;
4066   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4067   int serial;
4068
4069   if (check_state (g, "guestfs_umount") == -1) return -1;
4070   guestfs_set_busy (g);
4071
4072   memset (&ctx, 0, sizeof ctx);
4073
4074   args.pathordevice = (char *) pathordevice;
4075   serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT,
4076         (xdrproc_t) xdr_guestfs_umount_args, (char *) &args);
4077   if (serial == -1) {
4078     guestfs_set_ready (g);
4079     return -1;
4080   }
4081
4082   guestfs__switch_to_receiving (g);
4083   ctx.cb_sequence = 0;
4084   guestfs_set_reply_callback (g, umount_reply_cb, &ctx);
4085   (void) ml->main_loop_run (ml, g);
4086   guestfs_set_reply_callback (g, NULL, NULL);
4087   if (ctx.cb_sequence != 1) {
4088     error (g, "%s reply failed, see earlier error messages", "guestfs_umount");
4089     guestfs_set_ready (g);
4090     return -1;
4091   }
4092
4093   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT, serial) == -1) {
4094     guestfs_set_ready (g);
4095     return -1;
4096   }
4097
4098   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4099     error (g, "%s", ctx.err.error_message);
4100     guestfs_set_ready (g);
4101     return -1;
4102   }
4103
4104   guestfs_set_ready (g);
4105   return 0;
4106 }
4107
4108 struct mounts_ctx {
4109   /* This flag is set by the callbacks, so we know we've done
4110    * the callbacks as expected, and in the right sequence.
4111    * 0 = not called, 1 = reply_cb called.
4112    */
4113   int cb_sequence;
4114   struct guestfs_message_header hdr;
4115   struct guestfs_message_error err;
4116   struct guestfs_mounts_ret ret;
4117 };
4118
4119 static void mounts_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4120 {
4121   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4122   struct mounts_ctx *ctx = (struct mounts_ctx *) data;
4123
4124   /* This should definitely not happen. */
4125   if (ctx->cb_sequence != 0) {
4126     ctx->cb_sequence = 9999;
4127     error (g, "%s: internal error: reply callback called twice", "guestfs_mounts");
4128     return;
4129   }
4130
4131   ml->main_loop_quit (ml, g);
4132
4133   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4134     error (g, "%s: failed to parse reply header", "guestfs_mounts");
4135     return;
4136   }
4137   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4138     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4139       error (g, "%s: failed to parse reply error", "guestfs_mounts");
4140       return;
4141     }
4142     goto done;
4143   }
4144   if (!xdr_guestfs_mounts_ret (xdr, &ctx->ret)) {
4145     error (g, "%s: failed to parse reply", "guestfs_mounts");
4146     return;
4147   }
4148  done:
4149   ctx->cb_sequence = 1;
4150 }
4151
4152 char **guestfs_mounts (guestfs_h *g)
4153 {
4154   struct mounts_ctx ctx;
4155   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4156   int serial;
4157
4158   if (check_state (g, "guestfs_mounts") == -1) return NULL;
4159   guestfs_set_busy (g);
4160
4161   memset (&ctx, 0, sizeof ctx);
4162
4163   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
4164   if (serial == -1) {
4165     guestfs_set_ready (g);
4166     return NULL;
4167   }
4168
4169   guestfs__switch_to_receiving (g);
4170   ctx.cb_sequence = 0;
4171   guestfs_set_reply_callback (g, mounts_reply_cb, &ctx);
4172   (void) ml->main_loop_run (ml, g);
4173   guestfs_set_reply_callback (g, NULL, NULL);
4174   if (ctx.cb_sequence != 1) {
4175     error (g, "%s reply failed, see earlier error messages", "guestfs_mounts");
4176     guestfs_set_ready (g);
4177     return NULL;
4178   }
4179
4180   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNTS, serial) == -1) {
4181     guestfs_set_ready (g);
4182     return NULL;
4183   }
4184
4185   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4186     error (g, "%s", ctx.err.error_message);
4187     guestfs_set_ready (g);
4188     return NULL;
4189   }
4190
4191   guestfs_set_ready (g);
4192   /* caller will free this, but we need to add a NULL entry */
4193   ctx.ret.devices.devices_val =
4194     safe_realloc (g, ctx.ret.devices.devices_val,
4195                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
4196   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
4197   return ctx.ret.devices.devices_val;
4198 }
4199
4200 struct umount_all_ctx {
4201   /* This flag is set by the callbacks, so we know we've done
4202    * the callbacks as expected, and in the right sequence.
4203    * 0 = not called, 1 = reply_cb called.
4204    */
4205   int cb_sequence;
4206   struct guestfs_message_header hdr;
4207   struct guestfs_message_error err;
4208 };
4209
4210 static void umount_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4211 {
4212   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4213   struct umount_all_ctx *ctx = (struct umount_all_ctx *) data;
4214
4215   /* This should definitely not happen. */
4216   if (ctx->cb_sequence != 0) {
4217     ctx->cb_sequence = 9999;
4218     error (g, "%s: internal error: reply callback called twice", "guestfs_umount_all");
4219     return;
4220   }
4221
4222   ml->main_loop_quit (ml, g);
4223
4224   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4225     error (g, "%s: failed to parse reply header", "guestfs_umount_all");
4226     return;
4227   }
4228   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4229     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4230       error (g, "%s: failed to parse reply error", "guestfs_umount_all");
4231       return;
4232     }
4233     goto done;
4234   }
4235  done:
4236   ctx->cb_sequence = 1;
4237 }
4238
4239 int guestfs_umount_all (guestfs_h *g)
4240 {
4241   struct umount_all_ctx ctx;
4242   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4243   int serial;
4244
4245   if (check_state (g, "guestfs_umount_all") == -1) return -1;
4246   guestfs_set_busy (g);
4247
4248   memset (&ctx, 0, sizeof ctx);
4249
4250   serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
4251   if (serial == -1) {
4252     guestfs_set_ready (g);
4253     return -1;
4254   }
4255
4256   guestfs__switch_to_receiving (g);
4257   ctx.cb_sequence = 0;
4258   guestfs_set_reply_callback (g, umount_all_reply_cb, &ctx);
4259   (void) ml->main_loop_run (ml, g);
4260   guestfs_set_reply_callback (g, NULL, NULL);
4261   if (ctx.cb_sequence != 1) {
4262     error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all");
4263     guestfs_set_ready (g);
4264     return -1;
4265   }
4266
4267   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1) {
4268     guestfs_set_ready (g);
4269     return -1;
4270   }
4271
4272   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4273     error (g, "%s", ctx.err.error_message);
4274     guestfs_set_ready (g);
4275     return -1;
4276   }
4277
4278   guestfs_set_ready (g);
4279   return 0;
4280 }
4281
4282 struct lvm_remove_all_ctx {
4283   /* This flag is set by the callbacks, so we know we've done
4284    * the callbacks as expected, and in the right sequence.
4285    * 0 = not called, 1 = reply_cb called.
4286    */
4287   int cb_sequence;
4288   struct guestfs_message_header hdr;
4289   struct guestfs_message_error err;
4290 };
4291
4292 static void lvm_remove_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4293 {
4294   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4295   struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data;
4296
4297   /* This should definitely not happen. */
4298   if (ctx->cb_sequence != 0) {
4299     ctx->cb_sequence = 9999;
4300     error (g, "%s: internal error: reply callback called twice", "guestfs_lvm_remove_all");
4301     return;
4302   }
4303
4304   ml->main_loop_quit (ml, g);
4305
4306   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4307     error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all");
4308     return;
4309   }
4310   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4311     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4312       error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all");
4313       return;
4314     }
4315     goto done;
4316   }
4317  done:
4318   ctx->cb_sequence = 1;
4319 }
4320
4321 int guestfs_lvm_remove_all (guestfs_h *g)
4322 {
4323   struct lvm_remove_all_ctx ctx;
4324   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4325   int serial;
4326
4327   if (check_state (g, "guestfs_lvm_remove_all") == -1) return -1;
4328   guestfs_set_busy (g);
4329
4330   memset (&ctx, 0, sizeof ctx);
4331
4332   serial = guestfs__send_sync (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
4333   if (serial == -1) {
4334     guestfs_set_ready (g);
4335     return -1;
4336   }
4337
4338   guestfs__switch_to_receiving (g);
4339   ctx.cb_sequence = 0;
4340   guestfs_set_reply_callback (g, lvm_remove_all_reply_cb, &ctx);
4341   (void) ml->main_loop_run (ml, g);
4342   guestfs_set_reply_callback (g, NULL, NULL);
4343   if (ctx.cb_sequence != 1) {
4344     error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all");
4345     guestfs_set_ready (g);
4346     return -1;
4347   }
4348
4349   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1) {
4350     guestfs_set_ready (g);
4351     return -1;
4352   }
4353
4354   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4355     error (g, "%s", ctx.err.error_message);
4356     guestfs_set_ready (g);
4357     return -1;
4358   }
4359
4360   guestfs_set_ready (g);
4361   return 0;
4362 }
4363
4364 struct file_ctx {
4365   /* This flag is set by the callbacks, so we know we've done
4366    * the callbacks as expected, and in the right sequence.
4367    * 0 = not called, 1 = reply_cb called.
4368    */
4369   int cb_sequence;
4370   struct guestfs_message_header hdr;
4371   struct guestfs_message_error err;
4372   struct guestfs_file_ret ret;
4373 };
4374
4375 static void file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4376 {
4377   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4378   struct file_ctx *ctx = (struct file_ctx *) data;
4379
4380   /* This should definitely not happen. */
4381   if (ctx->cb_sequence != 0) {
4382     ctx->cb_sequence = 9999;
4383     error (g, "%s: internal error: reply callback called twice", "guestfs_file");
4384     return;
4385   }
4386
4387   ml->main_loop_quit (ml, g);
4388
4389   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4390     error (g, "%s: failed to parse reply header", "guestfs_file");
4391     return;
4392   }
4393   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4394     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4395       error (g, "%s: failed to parse reply error", "guestfs_file");
4396       return;
4397     }
4398     goto done;
4399   }
4400   if (!xdr_guestfs_file_ret (xdr, &ctx->ret)) {
4401     error (g, "%s: failed to parse reply", "guestfs_file");
4402     return;
4403   }
4404  done:
4405   ctx->cb_sequence = 1;
4406 }
4407
4408 char *guestfs_file (guestfs_h *g,
4409                 const char *path)
4410 {
4411   struct guestfs_file_args args;
4412   struct file_ctx ctx;
4413   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4414   int serial;
4415
4416   if (check_state (g, "guestfs_file") == -1) return NULL;
4417   guestfs_set_busy (g);
4418
4419   memset (&ctx, 0, sizeof ctx);
4420
4421   args.path = (char *) path;
4422   serial = guestfs__send_sync (g, GUESTFS_PROC_FILE,
4423         (xdrproc_t) xdr_guestfs_file_args, (char *) &args);
4424   if (serial == -1) {
4425     guestfs_set_ready (g);
4426     return NULL;
4427   }
4428
4429   guestfs__switch_to_receiving (g);
4430   ctx.cb_sequence = 0;
4431   guestfs_set_reply_callback (g, file_reply_cb, &ctx);
4432   (void) ml->main_loop_run (ml, g);
4433   guestfs_set_reply_callback (g, NULL, NULL);
4434   if (ctx.cb_sequence != 1) {
4435     error (g, "%s reply failed, see earlier error messages", "guestfs_file");
4436     guestfs_set_ready (g);
4437     return NULL;
4438   }
4439
4440   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FILE, serial) == -1) {
4441     guestfs_set_ready (g);
4442     return NULL;
4443   }
4444
4445   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4446     error (g, "%s", ctx.err.error_message);
4447     guestfs_set_ready (g);
4448     return NULL;
4449   }
4450
4451   guestfs_set_ready (g);
4452   return ctx.ret.description; /* caller will free */
4453 }
4454
4455 struct command_ctx {
4456   /* This flag is set by the callbacks, so we know we've done
4457    * the callbacks as expected, and in the right sequence.
4458    * 0 = not called, 1 = reply_cb called.
4459    */
4460   int cb_sequence;
4461   struct guestfs_message_header hdr;
4462   struct guestfs_message_error err;
4463   struct guestfs_command_ret ret;
4464 };
4465
4466 static void command_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4467 {
4468   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4469   struct command_ctx *ctx = (struct command_ctx *) data;
4470
4471   /* This should definitely not happen. */
4472   if (ctx->cb_sequence != 0) {
4473     ctx->cb_sequence = 9999;
4474     error (g, "%s: internal error: reply callback called twice", "guestfs_command");
4475     return;
4476   }
4477
4478   ml->main_loop_quit (ml, g);
4479
4480   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4481     error (g, "%s: failed to parse reply header", "guestfs_command");
4482     return;
4483   }
4484   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4485     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4486       error (g, "%s: failed to parse reply error", "guestfs_command");
4487       return;
4488     }
4489     goto done;
4490   }
4491   if (!xdr_guestfs_command_ret (xdr, &ctx->ret)) {
4492     error (g, "%s: failed to parse reply", "guestfs_command");
4493     return;
4494   }
4495  done:
4496   ctx->cb_sequence = 1;
4497 }
4498
4499 char *guestfs_command (guestfs_h *g,
4500                 char * const* const arguments)
4501 {
4502   struct guestfs_command_args args;
4503   struct command_ctx ctx;
4504   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4505   int serial;
4506
4507   if (check_state (g, "guestfs_command") == -1) return NULL;
4508   guestfs_set_busy (g);
4509
4510   memset (&ctx, 0, sizeof ctx);
4511
4512   args.arguments.arguments_val = (char **) arguments;
4513   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4514   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND,
4515         (xdrproc_t) xdr_guestfs_command_args, (char *) &args);
4516   if (serial == -1) {
4517     guestfs_set_ready (g);
4518     return NULL;
4519   }
4520
4521   guestfs__switch_to_receiving (g);
4522   ctx.cb_sequence = 0;
4523   guestfs_set_reply_callback (g, command_reply_cb, &ctx);
4524   (void) ml->main_loop_run (ml, g);
4525   guestfs_set_reply_callback (g, NULL, NULL);
4526   if (ctx.cb_sequence != 1) {
4527     error (g, "%s reply failed, see earlier error messages", "guestfs_command");
4528     guestfs_set_ready (g);
4529     return NULL;
4530   }
4531
4532   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND, serial) == -1) {
4533     guestfs_set_ready (g);
4534     return NULL;
4535   }
4536
4537   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4538     error (g, "%s", ctx.err.error_message);
4539     guestfs_set_ready (g);
4540     return NULL;
4541   }
4542
4543   guestfs_set_ready (g);
4544   return ctx.ret.output; /* caller will free */
4545 }
4546
4547 struct command_lines_ctx {
4548   /* This flag is set by the callbacks, so we know we've done
4549    * the callbacks as expected, and in the right sequence.
4550    * 0 = not called, 1 = reply_cb called.
4551    */
4552   int cb_sequence;
4553   struct guestfs_message_header hdr;
4554   struct guestfs_message_error err;
4555   struct guestfs_command_lines_ret ret;
4556 };
4557
4558 static void command_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4559 {
4560   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4561   struct command_lines_ctx *ctx = (struct command_lines_ctx *) data;
4562
4563   /* This should definitely not happen. */
4564   if (ctx->cb_sequence != 0) {
4565     ctx->cb_sequence = 9999;
4566     error (g, "%s: internal error: reply callback called twice", "guestfs_command_lines");
4567     return;
4568   }
4569
4570   ml->main_loop_quit (ml, g);
4571
4572   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4573     error (g, "%s: failed to parse reply header", "guestfs_command_lines");
4574     return;
4575   }
4576   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4577     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4578       error (g, "%s: failed to parse reply error", "guestfs_command_lines");
4579       return;
4580     }
4581     goto done;
4582   }
4583   if (!xdr_guestfs_command_lines_ret (xdr, &ctx->ret)) {
4584     error (g, "%s: failed to parse reply", "guestfs_command_lines");
4585     return;
4586   }
4587  done:
4588   ctx->cb_sequence = 1;
4589 }
4590
4591 char **guestfs_command_lines (guestfs_h *g,
4592                 char * const* const arguments)
4593 {
4594   struct guestfs_command_lines_args args;
4595   struct command_lines_ctx ctx;
4596   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4597   int serial;
4598
4599   if (check_state (g, "guestfs_command_lines") == -1) return NULL;
4600   guestfs_set_busy (g);
4601
4602   memset (&ctx, 0, sizeof ctx);
4603
4604   args.arguments.arguments_val = (char **) arguments;
4605   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4606   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND_LINES,
4607         (xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args);
4608   if (serial == -1) {
4609     guestfs_set_ready (g);
4610     return NULL;
4611   }
4612
4613   guestfs__switch_to_receiving (g);
4614   ctx.cb_sequence = 0;
4615   guestfs_set_reply_callback (g, command_lines_reply_cb, &ctx);
4616   (void) ml->main_loop_run (ml, g);
4617   guestfs_set_reply_callback (g, NULL, NULL);
4618   if (ctx.cb_sequence != 1) {
4619     error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines");
4620     guestfs_set_ready (g);
4621     return NULL;
4622   }
4623
4624   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1) {
4625     guestfs_set_ready (g);
4626     return NULL;
4627   }
4628
4629   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4630     error (g, "%s", ctx.err.error_message);
4631     guestfs_set_ready (g);
4632     return NULL;
4633   }
4634
4635   guestfs_set_ready (g);
4636   /* caller will free this, but we need to add a NULL entry */
4637   ctx.ret.lines.lines_val =
4638     safe_realloc (g, ctx.ret.lines.lines_val,
4639                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
4640   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
4641   return ctx.ret.lines.lines_val;
4642 }
4643
4644 struct stat_ctx {
4645   /* This flag is set by the callbacks, so we know we've done
4646    * the callbacks as expected, and in the right sequence.
4647    * 0 = not called, 1 = reply_cb called.
4648    */
4649   int cb_sequence;
4650   struct guestfs_message_header hdr;
4651   struct guestfs_message_error err;
4652   struct guestfs_stat_ret ret;
4653 };
4654
4655 static void stat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4656 {
4657   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4658   struct stat_ctx *ctx = (struct stat_ctx *) data;
4659
4660   /* This should definitely not happen. */
4661   if (ctx->cb_sequence != 0) {
4662     ctx->cb_sequence = 9999;
4663     error (g, "%s: internal error: reply callback called twice", "guestfs_stat");
4664     return;
4665   }
4666
4667   ml->main_loop_quit (ml, g);
4668
4669   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4670     error (g, "%s: failed to parse reply header", "guestfs_stat");
4671     return;
4672   }
4673   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4674     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4675       error (g, "%s: failed to parse reply error", "guestfs_stat");
4676       return;
4677     }
4678     goto done;
4679   }
4680   if (!xdr_guestfs_stat_ret (xdr, &ctx->ret)) {
4681     error (g, "%s: failed to parse reply", "guestfs_stat");
4682     return;
4683   }
4684  done:
4685   ctx->cb_sequence = 1;
4686 }
4687
4688 struct guestfs_stat *guestfs_stat (guestfs_h *g,
4689                 const char *path)
4690 {
4691   struct guestfs_stat_args args;
4692   struct stat_ctx ctx;
4693   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4694   int serial;
4695
4696   if (check_state (g, "guestfs_stat") == -1) return NULL;
4697   guestfs_set_busy (g);
4698
4699   memset (&ctx, 0, sizeof ctx);
4700
4701   args.path = (char *) path;
4702   serial = guestfs__send_sync (g, GUESTFS_PROC_STAT,
4703         (xdrproc_t) xdr_guestfs_stat_args, (char *) &args);
4704   if (serial == -1) {
4705     guestfs_set_ready (g);
4706     return NULL;
4707   }
4708
4709   guestfs__switch_to_receiving (g);
4710   ctx.cb_sequence = 0;
4711   guestfs_set_reply_callback (g, stat_reply_cb, &ctx);
4712   (void) ml->main_loop_run (ml, g);
4713   guestfs_set_reply_callback (g, NULL, NULL);
4714   if (ctx.cb_sequence != 1) {
4715     error (g, "%s reply failed, see earlier error messages", "guestfs_stat");
4716     guestfs_set_ready (g);
4717     return NULL;
4718   }
4719
4720   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STAT, serial) == -1) {
4721     guestfs_set_ready (g);
4722     return NULL;
4723   }
4724
4725   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4726     error (g, "%s", ctx.err.error_message);
4727     guestfs_set_ready (g);
4728     return NULL;
4729   }
4730
4731   guestfs_set_ready (g);
4732   /* caller will free this */
4733   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4734 }
4735
4736 struct lstat_ctx {
4737   /* This flag is set by the callbacks, so we know we've done
4738    * the callbacks as expected, and in the right sequence.
4739    * 0 = not called, 1 = reply_cb called.
4740    */
4741   int cb_sequence;
4742   struct guestfs_message_header hdr;
4743   struct guestfs_message_error err;
4744   struct guestfs_lstat_ret ret;
4745 };
4746
4747 static void lstat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4748 {
4749   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4750   struct lstat_ctx *ctx = (struct lstat_ctx *) data;
4751
4752   /* This should definitely not happen. */
4753   if (ctx->cb_sequence != 0) {
4754     ctx->cb_sequence = 9999;
4755     error (g, "%s: internal error: reply callback called twice", "guestfs_lstat");
4756     return;
4757   }
4758
4759   ml->main_loop_quit (ml, g);
4760
4761   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4762     error (g, "%s: failed to parse reply header", "guestfs_lstat");
4763     return;
4764   }
4765   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4766     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4767       error (g, "%s: failed to parse reply error", "guestfs_lstat");
4768       return;
4769     }
4770     goto done;
4771   }
4772   if (!xdr_guestfs_lstat_ret (xdr, &ctx->ret)) {
4773     error (g, "%s: failed to parse reply", "guestfs_lstat");
4774     return;
4775   }
4776  done:
4777   ctx->cb_sequence = 1;
4778 }
4779
4780 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
4781                 const char *path)
4782 {
4783   struct guestfs_lstat_args args;
4784   struct lstat_ctx ctx;
4785   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4786   int serial;
4787
4788   if (check_state (g, "guestfs_lstat") == -1) return NULL;
4789   guestfs_set_busy (g);
4790
4791   memset (&ctx, 0, sizeof ctx);
4792
4793   args.path = (char *) path;
4794   serial = guestfs__send_sync (g, GUESTFS_PROC_LSTAT,
4795         (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args);
4796   if (serial == -1) {
4797     guestfs_set_ready (g);
4798     return NULL;
4799   }
4800
4801   guestfs__switch_to_receiving (g);
4802   ctx.cb_sequence = 0;
4803   guestfs_set_reply_callback (g, lstat_reply_cb, &ctx);
4804   (void) ml->main_loop_run (ml, g);
4805   guestfs_set_reply_callback (g, NULL, NULL);
4806   if (ctx.cb_sequence != 1) {
4807     error (g, "%s reply failed, see earlier error messages", "guestfs_lstat");
4808     guestfs_set_ready (g);
4809     return NULL;
4810   }
4811
4812   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LSTAT, serial) == -1) {
4813     guestfs_set_ready (g);
4814     return NULL;
4815   }
4816
4817   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4818     error (g, "%s", ctx.err.error_message);
4819     guestfs_set_ready (g);
4820     return NULL;
4821   }
4822
4823   guestfs_set_ready (g);
4824   /* caller will free this */
4825   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4826 }
4827
4828 struct statvfs_ctx {
4829   /* This flag is set by the callbacks, so we know we've done
4830    * the callbacks as expected, and in the right sequence.
4831    * 0 = not called, 1 = reply_cb called.
4832    */
4833   int cb_sequence;
4834   struct guestfs_message_header hdr;
4835   struct guestfs_message_error err;
4836   struct guestfs_statvfs_ret ret;
4837 };
4838
4839 static void statvfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4840 {
4841   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4842   struct statvfs_ctx *ctx = (struct statvfs_ctx *) data;
4843
4844   /* This should definitely not happen. */
4845   if (ctx->cb_sequence != 0) {
4846     ctx->cb_sequence = 9999;
4847     error (g, "%s: internal error: reply callback called twice", "guestfs_statvfs");
4848     return;
4849   }
4850
4851   ml->main_loop_quit (ml, g);
4852
4853   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4854     error (g, "%s: failed to parse reply header", "guestfs_statvfs");
4855     return;
4856   }
4857   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4858     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4859       error (g, "%s: failed to parse reply error", "guestfs_statvfs");
4860       return;
4861     }
4862     goto done;
4863   }
4864   if (!xdr_guestfs_statvfs_ret (xdr, &ctx->ret)) {
4865     error (g, "%s: failed to parse reply", "guestfs_statvfs");
4866     return;
4867   }
4868  done:
4869   ctx->cb_sequence = 1;
4870 }
4871
4872 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
4873                 const char *path)
4874 {
4875   struct guestfs_statvfs_args args;
4876   struct statvfs_ctx ctx;
4877   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4878   int serial;
4879
4880   if (check_state (g, "guestfs_statvfs") == -1) return NULL;
4881   guestfs_set_busy (g);
4882
4883   memset (&ctx, 0, sizeof ctx);
4884
4885   args.path = (char *) path;
4886   serial = guestfs__send_sync (g, GUESTFS_PROC_STATVFS,
4887         (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args);
4888   if (serial == -1) {
4889     guestfs_set_ready (g);
4890     return NULL;
4891   }
4892
4893   guestfs__switch_to_receiving (g);
4894   ctx.cb_sequence = 0;
4895   guestfs_set_reply_callback (g, statvfs_reply_cb, &ctx);
4896   (void) ml->main_loop_run (ml, g);
4897   guestfs_set_reply_callback (g, NULL, NULL);
4898   if (ctx.cb_sequence != 1) {
4899     error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs");
4900     guestfs_set_ready (g);
4901     return NULL;
4902   }
4903
4904   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STATVFS, serial) == -1) {
4905     guestfs_set_ready (g);
4906     return NULL;
4907   }
4908
4909   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4910     error (g, "%s", ctx.err.error_message);
4911     guestfs_set_ready (g);
4912     return NULL;
4913   }
4914
4915   guestfs_set_ready (g);
4916   /* caller will free this */
4917   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4918 }
4919
4920 struct tune2fs_l_ctx {
4921   /* This flag is set by the callbacks, so we know we've done
4922    * the callbacks as expected, and in the right sequence.
4923    * 0 = not called, 1 = reply_cb called.
4924    */
4925   int cb_sequence;
4926   struct guestfs_message_header hdr;
4927   struct guestfs_message_error err;
4928   struct guestfs_tune2fs_l_ret ret;
4929 };
4930
4931 static void tune2fs_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4932 {
4933   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4934   struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data;
4935
4936   /* This should definitely not happen. */
4937   if (ctx->cb_sequence != 0) {
4938     ctx->cb_sequence = 9999;
4939     error (g, "%s: internal error: reply callback called twice", "guestfs_tune2fs_l");
4940     return;
4941   }
4942
4943   ml->main_loop_quit (ml, g);
4944
4945   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4946     error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l");
4947     return;
4948   }
4949   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4950     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4951       error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l");
4952       return;
4953     }
4954     goto done;
4955   }
4956   if (!xdr_guestfs_tune2fs_l_ret (xdr, &ctx->ret)) {
4957     error (g, "%s: failed to parse reply", "guestfs_tune2fs_l");
4958     return;
4959   }
4960  done:
4961   ctx->cb_sequence = 1;
4962 }
4963
4964 char **guestfs_tune2fs_l (guestfs_h *g,
4965                 const char *device)
4966 {
4967   struct guestfs_tune2fs_l_args args;
4968   struct tune2fs_l_ctx ctx;
4969   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4970   int serial;
4971
4972   if (check_state (g, "guestfs_tune2fs_l") == -1) return NULL;
4973   guestfs_set_busy (g);
4974
4975   memset (&ctx, 0, sizeof ctx);
4976
4977   args.device = (char *) device;
4978   serial = guestfs__send_sync (g, GUESTFS_PROC_TUNE2FS_L,
4979         (xdrproc_t) xdr_guestfs_tune2fs_l_args, (char *) &args);
4980   if (serial == -1) {
4981     guestfs_set_ready (g);
4982     return NULL;
4983   }
4984
4985   guestfs__switch_to_receiving (g);
4986   ctx.cb_sequence = 0;
4987   guestfs_set_reply_callback (g, tune2fs_l_reply_cb, &ctx);
4988   (void) ml->main_loop_run (ml, g);
4989   guestfs_set_reply_callback (g, NULL, NULL);
4990   if (ctx.cb_sequence != 1) {
4991     error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l");
4992     guestfs_set_ready (g);
4993     return NULL;
4994   }
4995
4996   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1) {
4997     guestfs_set_ready (g);
4998     return NULL;
4999   }
5000
5001   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5002     error (g, "%s", ctx.err.error_message);
5003     guestfs_set_ready (g);
5004     return NULL;
5005   }
5006
5007   guestfs_set_ready (g);
5008   /* caller will free this, but we need to add a NULL entry */
5009   ctx.ret.superblock.superblock_val =
5010     safe_realloc (g, ctx.ret.superblock.superblock_val,
5011                   sizeof (char *) * (ctx.ret.superblock.superblock_len + 1));
5012   ctx.ret.superblock.superblock_val[ctx.ret.superblock.superblock_len] = NULL;
5013   return ctx.ret.superblock.superblock_val;
5014 }
5015
5016 struct blockdev_setro_ctx {
5017   /* This flag is set by the callbacks, so we know we've done
5018    * the callbacks as expected, and in the right sequence.
5019    * 0 = not called, 1 = reply_cb called.
5020    */
5021   int cb_sequence;
5022   struct guestfs_message_header hdr;
5023   struct guestfs_message_error err;
5024 };
5025
5026 static void blockdev_setro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5027 {
5028   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5029   struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data;
5030
5031   /* This should definitely not happen. */
5032   if (ctx->cb_sequence != 0) {
5033     ctx->cb_sequence = 9999;
5034     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setro");
5035     return;
5036   }
5037
5038   ml->main_loop_quit (ml, g);
5039
5040   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5041     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro");
5042     return;
5043   }
5044   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5045     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5046       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro");
5047       return;
5048     }
5049     goto done;
5050   }
5051  done:
5052   ctx->cb_sequence = 1;
5053 }
5054
5055 int guestfs_blockdev_setro (guestfs_h *g,
5056                 const char *device)
5057 {
5058   struct guestfs_blockdev_setro_args args;
5059   struct blockdev_setro_ctx ctx;
5060   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5061   int serial;
5062
5063   if (check_state (g, "guestfs_blockdev_setro") == -1) return -1;
5064   guestfs_set_busy (g);
5065
5066   memset (&ctx, 0, sizeof ctx);
5067
5068   args.device = (char *) device;
5069   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRO,
5070         (xdrproc_t) xdr_guestfs_blockdev_setro_args, (char *) &args);
5071   if (serial == -1) {
5072     guestfs_set_ready (g);
5073     return -1;
5074   }
5075
5076   guestfs__switch_to_receiving (g);
5077   ctx.cb_sequence = 0;
5078   guestfs_set_reply_callback (g, blockdev_setro_reply_cb, &ctx);
5079   (void) ml->main_loop_run (ml, g);
5080   guestfs_set_reply_callback (g, NULL, NULL);
5081   if (ctx.cb_sequence != 1) {
5082     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro");
5083     guestfs_set_ready (g);
5084     return -1;
5085   }
5086
5087   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1) {
5088     guestfs_set_ready (g);
5089     return -1;
5090   }
5091
5092   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5093     error (g, "%s", ctx.err.error_message);
5094     guestfs_set_ready (g);
5095     return -1;
5096   }
5097
5098   guestfs_set_ready (g);
5099   return 0;
5100 }
5101
5102 struct blockdev_setrw_ctx {
5103   /* This flag is set by the callbacks, so we know we've done
5104    * the callbacks as expected, and in the right sequence.
5105    * 0 = not called, 1 = reply_cb called.
5106    */
5107   int cb_sequence;
5108   struct guestfs_message_header hdr;
5109   struct guestfs_message_error err;
5110 };
5111
5112 static void blockdev_setrw_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5113 {
5114   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5115   struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data;
5116
5117   /* This should definitely not happen. */
5118   if (ctx->cb_sequence != 0) {
5119     ctx->cb_sequence = 9999;
5120     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setrw");
5121     return;
5122   }
5123
5124   ml->main_loop_quit (ml, g);
5125
5126   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5127     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw");
5128     return;
5129   }
5130   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5131     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5132       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw");
5133       return;
5134     }
5135     goto done;
5136   }
5137  done:
5138   ctx->cb_sequence = 1;
5139 }
5140
5141 int guestfs_blockdev_setrw (guestfs_h *g,
5142                 const char *device)
5143 {
5144   struct guestfs_blockdev_setrw_args args;
5145   struct blockdev_setrw_ctx ctx;
5146   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5147   int serial;
5148
5149   if (check_state (g, "guestfs_blockdev_setrw") == -1) return -1;
5150   guestfs_set_busy (g);
5151
5152   memset (&ctx, 0, sizeof ctx);
5153
5154   args.device = (char *) device;
5155   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRW,
5156         (xdrproc_t) xdr_guestfs_blockdev_setrw_args, (char *) &args);
5157   if (serial == -1) {
5158     guestfs_set_ready (g);
5159     return -1;
5160   }
5161
5162   guestfs__switch_to_receiving (g);
5163   ctx.cb_sequence = 0;
5164   guestfs_set_reply_callback (g, blockdev_setrw_reply_cb, &ctx);
5165   (void) ml->main_loop_run (ml, g);
5166   guestfs_set_reply_callback (g, NULL, NULL);
5167   if (ctx.cb_sequence != 1) {
5168     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw");
5169     guestfs_set_ready (g);
5170     return -1;
5171   }
5172
5173   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1) {
5174     guestfs_set_ready (g);
5175     return -1;
5176   }
5177
5178   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5179     error (g, "%s", ctx.err.error_message);
5180     guestfs_set_ready (g);
5181     return -1;
5182   }
5183
5184   guestfs_set_ready (g);
5185   return 0;
5186 }
5187
5188 struct blockdev_getro_ctx {
5189   /* This flag is set by the callbacks, so we know we've done
5190    * the callbacks as expected, and in the right sequence.
5191    * 0 = not called, 1 = reply_cb called.
5192    */
5193   int cb_sequence;
5194   struct guestfs_message_header hdr;
5195   struct guestfs_message_error err;
5196   struct guestfs_blockdev_getro_ret ret;
5197 };
5198
5199 static void blockdev_getro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5200 {
5201   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5202   struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data;
5203
5204   /* This should definitely not happen. */
5205   if (ctx->cb_sequence != 0) {
5206     ctx->cb_sequence = 9999;
5207     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getro");
5208     return;
5209   }
5210
5211   ml->main_loop_quit (ml, g);
5212
5213   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5214     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro");
5215     return;
5216   }
5217   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5218     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5219       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro");
5220       return;
5221     }
5222     goto done;
5223   }
5224   if (!xdr_guestfs_blockdev_getro_ret (xdr, &ctx->ret)) {
5225     error (g, "%s: failed to parse reply", "guestfs_blockdev_getro");
5226     return;
5227   }
5228  done:
5229   ctx->cb_sequence = 1;
5230 }
5231
5232 int guestfs_blockdev_getro (guestfs_h *g,
5233                 const char *device)
5234 {
5235   struct guestfs_blockdev_getro_args args;
5236   struct blockdev_getro_ctx ctx;
5237   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5238   int serial;
5239
5240   if (check_state (g, "guestfs_blockdev_getro") == -1) return -1;
5241   guestfs_set_busy (g);
5242
5243   memset (&ctx, 0, sizeof ctx);
5244
5245   args.device = (char *) device;
5246   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETRO,
5247         (xdrproc_t) xdr_guestfs_blockdev_getro_args, (char *) &args);
5248   if (serial == -1) {
5249     guestfs_set_ready (g);
5250     return -1;
5251   }
5252
5253   guestfs__switch_to_receiving (g);
5254   ctx.cb_sequence = 0;
5255   guestfs_set_reply_callback (g, blockdev_getro_reply_cb, &ctx);
5256   (void) ml->main_loop_run (ml, g);
5257   guestfs_set_reply_callback (g, NULL, NULL);
5258   if (ctx.cb_sequence != 1) {
5259     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro");
5260     guestfs_set_ready (g);
5261     return -1;
5262   }
5263
5264   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1) {
5265     guestfs_set_ready (g);
5266     return -1;
5267   }
5268
5269   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5270     error (g, "%s", ctx.err.error_message);
5271     guestfs_set_ready (g);
5272     return -1;
5273   }
5274
5275   guestfs_set_ready (g);
5276   return ctx.ret.ro;
5277 }
5278
5279 struct blockdev_getss_ctx {
5280   /* This flag is set by the callbacks, so we know we've done
5281    * the callbacks as expected, and in the right sequence.
5282    * 0 = not called, 1 = reply_cb called.
5283    */
5284   int cb_sequence;
5285   struct guestfs_message_header hdr;
5286   struct guestfs_message_error err;
5287   struct guestfs_blockdev_getss_ret ret;
5288 };
5289
5290 static void blockdev_getss_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5291 {
5292   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5293   struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data;
5294
5295   /* This should definitely not happen. */
5296   if (ctx->cb_sequence != 0) {
5297     ctx->cb_sequence = 9999;
5298     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getss");
5299     return;
5300   }
5301
5302   ml->main_loop_quit (ml, g);
5303
5304   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5305     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss");
5306     return;
5307   }
5308   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5309     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5310       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss");
5311       return;
5312     }
5313     goto done;
5314   }
5315   if (!xdr_guestfs_blockdev_getss_ret (xdr, &ctx->ret)) {
5316     error (g, "%s: failed to parse reply", "guestfs_blockdev_getss");
5317     return;
5318   }
5319  done:
5320   ctx->cb_sequence = 1;
5321 }
5322
5323 int guestfs_blockdev_getss (guestfs_h *g,
5324                 const char *device)
5325 {
5326   struct guestfs_blockdev_getss_args args;
5327   struct blockdev_getss_ctx ctx;
5328   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5329   int serial;
5330
5331   if (check_state (g, "guestfs_blockdev_getss") == -1) return -1;
5332   guestfs_set_busy (g);
5333
5334   memset (&ctx, 0, sizeof ctx);
5335
5336   args.device = (char *) device;
5337   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSS,
5338         (xdrproc_t) xdr_guestfs_blockdev_getss_args, (char *) &args);
5339   if (serial == -1) {
5340     guestfs_set_ready (g);
5341     return -1;
5342   }
5343
5344   guestfs__switch_to_receiving (g);
5345   ctx.cb_sequence = 0;
5346   guestfs_set_reply_callback (g, blockdev_getss_reply_cb, &ctx);
5347   (void) ml->main_loop_run (ml, g);
5348   guestfs_set_reply_callback (g, NULL, NULL);
5349   if (ctx.cb_sequence != 1) {
5350     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss");
5351     guestfs_set_ready (g);
5352     return -1;
5353   }
5354
5355   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1) {
5356     guestfs_set_ready (g);
5357     return -1;
5358   }
5359
5360   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5361     error (g, "%s", ctx.err.error_message);
5362     guestfs_set_ready (g);
5363     return -1;
5364   }
5365
5366   guestfs_set_ready (g);
5367   return ctx.ret.sectorsize;
5368 }
5369
5370 struct blockdev_getbsz_ctx {
5371   /* This flag is set by the callbacks, so we know we've done
5372    * the callbacks as expected, and in the right sequence.
5373    * 0 = not called, 1 = reply_cb called.
5374    */
5375   int cb_sequence;
5376   struct guestfs_message_header hdr;
5377   struct guestfs_message_error err;
5378   struct guestfs_blockdev_getbsz_ret ret;
5379 };
5380
5381 static void blockdev_getbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5382 {
5383   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5384   struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data;
5385
5386   /* This should definitely not happen. */
5387   if (ctx->cb_sequence != 0) {
5388     ctx->cb_sequence = 9999;
5389     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getbsz");
5390     return;
5391   }
5392
5393   ml->main_loop_quit (ml, g);
5394
5395   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5396     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz");
5397     return;
5398   }
5399   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5400     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5401       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz");
5402       return;
5403     }
5404     goto done;
5405   }
5406   if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &ctx->ret)) {
5407     error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz");
5408     return;
5409   }
5410  done:
5411   ctx->cb_sequence = 1;
5412 }
5413
5414 int guestfs_blockdev_getbsz (guestfs_h *g,
5415                 const char *device)
5416 {
5417   struct guestfs_blockdev_getbsz_args args;
5418   struct blockdev_getbsz_ctx ctx;
5419   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5420   int serial;
5421
5422   if (check_state (g, "guestfs_blockdev_getbsz") == -1) return -1;
5423   guestfs_set_busy (g);
5424
5425   memset (&ctx, 0, sizeof ctx);
5426
5427   args.device = (char *) device;
5428   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
5429         (xdrproc_t) xdr_guestfs_blockdev_getbsz_args, (char *) &args);
5430   if (serial == -1) {
5431     guestfs_set_ready (g);
5432     return -1;
5433   }
5434
5435   guestfs__switch_to_receiving (g);
5436   ctx.cb_sequence = 0;
5437   guestfs_set_reply_callback (g, blockdev_getbsz_reply_cb, &ctx);
5438   (void) ml->main_loop_run (ml, g);
5439   guestfs_set_reply_callback (g, NULL, NULL);
5440   if (ctx.cb_sequence != 1) {
5441     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz");
5442     guestfs_set_ready (g);
5443     return -1;
5444   }
5445
5446   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1) {
5447     guestfs_set_ready (g);
5448     return -1;
5449   }
5450
5451   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5452     error (g, "%s", ctx.err.error_message);
5453     guestfs_set_ready (g);
5454     return -1;
5455   }
5456
5457   guestfs_set_ready (g);
5458   return ctx.ret.blocksize;
5459 }
5460
5461 struct blockdev_setbsz_ctx {
5462   /* This flag is set by the callbacks, so we know we've done
5463    * the callbacks as expected, and in the right sequence.
5464    * 0 = not called, 1 = reply_cb called.
5465    */
5466   int cb_sequence;
5467   struct guestfs_message_header hdr;
5468   struct guestfs_message_error err;
5469 };
5470
5471 static void blockdev_setbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5472 {
5473   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5474   struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data;
5475
5476   /* This should definitely not happen. */
5477   if (ctx->cb_sequence != 0) {
5478     ctx->cb_sequence = 9999;
5479     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setbsz");
5480     return;
5481   }
5482
5483   ml->main_loop_quit (ml, g);
5484
5485   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5486     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz");
5487     return;
5488   }
5489   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5490     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5491       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz");
5492       return;
5493     }
5494     goto done;
5495   }
5496  done:
5497   ctx->cb_sequence = 1;
5498 }
5499
5500 int guestfs_blockdev_setbsz (guestfs_h *g,
5501                 const char *device,
5502                 int blocksize)
5503 {
5504   struct guestfs_blockdev_setbsz_args args;
5505   struct blockdev_setbsz_ctx ctx;
5506   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5507   int serial;
5508
5509   if (check_state (g, "guestfs_blockdev_setbsz") == -1) return -1;
5510   guestfs_set_busy (g);
5511
5512   memset (&ctx, 0, sizeof ctx);
5513
5514   args.device = (char *) device;
5515   args.blocksize = blocksize;
5516   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETBSZ,
5517         (xdrproc_t) xdr_guestfs_blockdev_setbsz_args, (char *) &args);
5518   if (serial == -1) {
5519     guestfs_set_ready (g);
5520     return -1;
5521   }
5522
5523   guestfs__switch_to_receiving (g);
5524   ctx.cb_sequence = 0;
5525   guestfs_set_reply_callback (g, blockdev_setbsz_reply_cb, &ctx);
5526   (void) ml->main_loop_run (ml, g);
5527   guestfs_set_reply_callback (g, NULL, NULL);
5528   if (ctx.cb_sequence != 1) {
5529     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz");
5530     guestfs_set_ready (g);
5531     return -1;
5532   }
5533
5534   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1) {
5535     guestfs_set_ready (g);
5536     return -1;
5537   }
5538
5539   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5540     error (g, "%s", ctx.err.error_message);
5541     guestfs_set_ready (g);
5542     return -1;
5543   }
5544
5545   guestfs_set_ready (g);
5546   return 0;
5547 }
5548
5549 struct blockdev_getsz_ctx {
5550   /* This flag is set by the callbacks, so we know we've done
5551    * the callbacks as expected, and in the right sequence.
5552    * 0 = not called, 1 = reply_cb called.
5553    */
5554   int cb_sequence;
5555   struct guestfs_message_header hdr;
5556   struct guestfs_message_error err;
5557   struct guestfs_blockdev_getsz_ret ret;
5558 };
5559
5560 static void blockdev_getsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5561 {
5562   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5563   struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data;
5564
5565   /* This should definitely not happen. */
5566   if (ctx->cb_sequence != 0) {
5567     ctx->cb_sequence = 9999;
5568     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getsz");
5569     return;
5570   }
5571
5572   ml->main_loop_quit (ml, g);
5573
5574   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5575     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz");
5576     return;
5577   }
5578   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5579     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5580       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz");
5581       return;
5582     }
5583     goto done;
5584   }
5585   if (!xdr_guestfs_blockdev_getsz_ret (xdr, &ctx->ret)) {
5586     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz");
5587     return;
5588   }
5589  done:
5590   ctx->cb_sequence = 1;
5591 }
5592
5593 int64_t guestfs_blockdev_getsz (guestfs_h *g,
5594                 const char *device)
5595 {
5596   struct guestfs_blockdev_getsz_args args;
5597   struct blockdev_getsz_ctx ctx;
5598   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5599   int serial;
5600
5601   if (check_state (g, "guestfs_blockdev_getsz") == -1) return -1;
5602   guestfs_set_busy (g);
5603
5604   memset (&ctx, 0, sizeof ctx);
5605
5606   args.device = (char *) device;
5607   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
5608         (xdrproc_t) xdr_guestfs_blockdev_getsz_args, (char *) &args);
5609   if (serial == -1) {
5610     guestfs_set_ready (g);
5611     return -1;
5612   }
5613
5614   guestfs__switch_to_receiving (g);
5615   ctx.cb_sequence = 0;
5616   guestfs_set_reply_callback (g, blockdev_getsz_reply_cb, &ctx);
5617   (void) ml->main_loop_run (ml, g);
5618   guestfs_set_reply_callback (g, NULL, NULL);
5619   if (ctx.cb_sequence != 1) {
5620     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz");
5621     guestfs_set_ready (g);
5622     return -1;
5623   }
5624
5625   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1) {
5626     guestfs_set_ready (g);
5627     return -1;
5628   }
5629
5630   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5631     error (g, "%s", ctx.err.error_message);
5632     guestfs_set_ready (g);
5633     return -1;
5634   }
5635
5636   guestfs_set_ready (g);
5637   return ctx.ret.sizeinsectors;
5638 }
5639
5640 struct blockdev_getsize64_ctx {
5641   /* This flag is set by the callbacks, so we know we've done
5642    * the callbacks as expected, and in the right sequence.
5643    * 0 = not called, 1 = reply_cb called.
5644    */
5645   int cb_sequence;
5646   struct guestfs_message_header hdr;
5647   struct guestfs_message_error err;
5648   struct guestfs_blockdev_getsize64_ret ret;
5649 };
5650
5651 static void blockdev_getsize64_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5652 {
5653   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5654   struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data;
5655
5656   /* This should definitely not happen. */
5657   if (ctx->cb_sequence != 0) {
5658     ctx->cb_sequence = 9999;
5659     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getsize64");
5660     return;
5661   }
5662
5663   ml->main_loop_quit (ml, g);
5664
5665   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5666     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64");
5667     return;
5668   }
5669   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5670     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5671       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64");
5672       return;
5673     }
5674     goto done;
5675   }
5676   if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &ctx->ret)) {
5677     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64");
5678     return;
5679   }
5680  done:
5681   ctx->cb_sequence = 1;
5682 }
5683
5684 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
5685                 const char *device)
5686 {
5687   struct guestfs_blockdev_getsize64_args args;
5688   struct blockdev_getsize64_ctx ctx;
5689   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5690   int serial;
5691
5692   if (check_state (g, "guestfs_blockdev_getsize64") == -1) return -1;
5693   guestfs_set_busy (g);
5694
5695   memset (&ctx, 0, sizeof ctx);
5696
5697   args.device = (char *) device;
5698   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
5699         (xdrproc_t) xdr_guestfs_blockdev_getsize64_args, (char *) &args);
5700   if (serial == -1) {
5701     guestfs_set_ready (g);
5702     return -1;
5703   }
5704
5705   guestfs__switch_to_receiving (g);
5706   ctx.cb_sequence = 0;
5707   guestfs_set_reply_callback (g, blockdev_getsize64_reply_cb, &ctx);
5708   (void) ml->main_loop_run (ml, g);
5709   guestfs_set_reply_callback (g, NULL, NULL);
5710   if (ctx.cb_sequence != 1) {
5711     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64");
5712     guestfs_set_ready (g);
5713     return -1;
5714   }
5715
5716   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1) {
5717     guestfs_set_ready (g);
5718     return -1;
5719   }
5720
5721   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5722     error (g, "%s", ctx.err.error_message);
5723     guestfs_set_ready (g);
5724     return -1;
5725   }
5726
5727   guestfs_set_ready (g);
5728   return ctx.ret.sizeinbytes;
5729 }
5730
5731 struct blockdev_flushbufs_ctx {
5732   /* This flag is set by the callbacks, so we know we've done
5733    * the callbacks as expected, and in the right sequence.
5734    * 0 = not called, 1 = reply_cb called.
5735    */
5736   int cb_sequence;
5737   struct guestfs_message_header hdr;
5738   struct guestfs_message_error err;
5739 };
5740
5741 static void blockdev_flushbufs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5742 {
5743   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5744   struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data;
5745
5746   /* This should definitely not happen. */
5747   if (ctx->cb_sequence != 0) {
5748     ctx->cb_sequence = 9999;
5749     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_flushbufs");
5750     return;
5751   }
5752
5753   ml->main_loop_quit (ml, g);
5754
5755   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5756     error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs");
5757     return;
5758   }
5759   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5760     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5761       error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs");
5762       return;
5763     }
5764     goto done;
5765   }
5766  done:
5767   ctx->cb_sequence = 1;
5768 }
5769
5770 int guestfs_blockdev_flushbufs (guestfs_h *g,
5771                 const char *device)
5772 {
5773   struct guestfs_blockdev_flushbufs_args args;
5774   struct blockdev_flushbufs_ctx ctx;
5775   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5776   int serial;
5777
5778   if (check_state (g, "guestfs_blockdev_flushbufs") == -1) return -1;
5779   guestfs_set_busy (g);
5780
5781   memset (&ctx, 0, sizeof ctx);
5782
5783   args.device = (char *) device;
5784   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
5785         (xdrproc_t) xdr_guestfs_blockdev_flushbufs_args, (char *) &args);
5786   if (serial == -1) {
5787     guestfs_set_ready (g);
5788     return -1;
5789   }
5790
5791   guestfs__switch_to_receiving (g);
5792   ctx.cb_sequence = 0;
5793   guestfs_set_reply_callback (g, blockdev_flushbufs_reply_cb, &ctx);
5794   (void) ml->main_loop_run (ml, g);
5795   guestfs_set_reply_callback (g, NULL, NULL);
5796   if (ctx.cb_sequence != 1) {
5797     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs");
5798     guestfs_set_ready (g);
5799     return -1;
5800   }
5801
5802   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1) {
5803     guestfs_set_ready (g);
5804     return -1;
5805   }
5806
5807   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5808     error (g, "%s", ctx.err.error_message);
5809     guestfs_set_ready (g);
5810     return -1;
5811   }
5812
5813   guestfs_set_ready (g);
5814   return 0;
5815 }
5816
5817 struct blockdev_rereadpt_ctx {
5818   /* This flag is set by the callbacks, so we know we've done
5819    * the callbacks as expected, and in the right sequence.
5820    * 0 = not called, 1 = reply_cb called.
5821    */
5822   int cb_sequence;
5823   struct guestfs_message_header hdr;
5824   struct guestfs_message_error err;
5825 };
5826
5827 static void blockdev_rereadpt_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5828 {
5829   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5830   struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data;
5831
5832   /* This should definitely not happen. */
5833   if (ctx->cb_sequence != 0) {
5834     ctx->cb_sequence = 9999;
5835     error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_rereadpt");
5836     return;
5837   }
5838
5839   ml->main_loop_quit (ml, g);
5840
5841   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5842     error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt");
5843     return;
5844   }
5845   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5846     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5847       error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt");
5848       return;
5849     }
5850     goto done;
5851   }
5852  done:
5853   ctx->cb_sequence = 1;
5854 }
5855
5856 int guestfs_blockdev_rereadpt (guestfs_h *g,
5857                 const char *device)
5858 {
5859   struct guestfs_blockdev_rereadpt_args args;
5860   struct blockdev_rereadpt_ctx ctx;
5861   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5862   int serial;
5863
5864   if (check_state (g, "guestfs_blockdev_rereadpt") == -1) return -1;
5865   guestfs_set_busy (g);
5866
5867   memset (&ctx, 0, sizeof ctx);
5868
5869   args.device = (char *) device;
5870   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
5871         (xdrproc_t) xdr_guestfs_blockdev_rereadpt_args, (char *) &args);
5872   if (serial == -1) {
5873     guestfs_set_ready (g);
5874     return -1;
5875   }
5876
5877   guestfs__switch_to_receiving (g);
5878   ctx.cb_sequence = 0;
5879   guestfs_set_reply_callback (g, blockdev_rereadpt_reply_cb, &ctx);
5880   (void) ml->main_loop_run (ml, g);
5881   guestfs_set_reply_callback (g, NULL, NULL);
5882   if (ctx.cb_sequence != 1) {
5883     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt");
5884     guestfs_set_ready (g);
5885     return -1;
5886   }
5887
5888   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1) {
5889     guestfs_set_ready (g);
5890     return -1;
5891   }
5892
5893   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5894     error (g, "%s", ctx.err.error_message);
5895     guestfs_set_ready (g);
5896     return -1;
5897   }
5898
5899   guestfs_set_ready (g);
5900   return 0;
5901 }
5902
5903 struct upload_ctx {
5904   /* This flag is set by the callbacks, so we know we've done
5905    * the callbacks as expected, and in the right sequence.
5906    * 0 = not called, 1 = reply_cb called.
5907    */
5908   int cb_sequence;
5909   struct guestfs_message_header hdr;
5910   struct guestfs_message_error err;
5911 };
5912
5913 static void upload_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5914 {
5915   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5916   struct upload_ctx *ctx = (struct upload_ctx *) data;
5917
5918   /* This should definitely not happen. */
5919   if (ctx->cb_sequence != 0) {
5920     ctx->cb_sequence = 9999;
5921     error (g, "%s: internal error: reply callback called twice", "guestfs_upload");
5922     return;
5923   }
5924
5925   ml->main_loop_quit (ml, g);
5926
5927   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5928     error (g, "%s: failed to parse reply header", "guestfs_upload");
5929     return;
5930   }
5931   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5932     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5933       error (g, "%s: failed to parse reply error", "guestfs_upload");
5934       return;
5935     }
5936     goto done;
5937   }
5938  done:
5939   ctx->cb_sequence = 1;
5940 }
5941
5942 int guestfs_upload (guestfs_h *g,
5943                 const char *filename,
5944                 const char *remotefilename)
5945 {
5946   struct guestfs_upload_args args;
5947   struct upload_ctx ctx;
5948   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5949   int serial;
5950
5951   if (check_state (g, "guestfs_upload") == -1) return -1;
5952   guestfs_set_busy (g);
5953
5954   memset (&ctx, 0, sizeof ctx);
5955
5956   args.remotefilename = (char *) remotefilename;
5957   serial = guestfs__send_sync (g, GUESTFS_PROC_UPLOAD,
5958         (xdrproc_t) xdr_guestfs_upload_args, (char *) &args);
5959   if (serial == -1) {
5960     guestfs_set_ready (g);
5961     return -1;
5962   }
5963
5964   {
5965     int r;
5966
5967     r = guestfs__send_file_sync (g, filename);
5968     if (r == -1) {
5969       guestfs_set_ready (g);
5970       return -1;
5971     }
5972     if (r == -2) /* daemon cancelled */
5973       goto read_reply;
5974   }
5975
5976  read_reply:
5977   guestfs__switch_to_receiving (g);
5978   ctx.cb_sequence = 0;
5979   guestfs_set_reply_callback (g, upload_reply_cb, &ctx);
5980   (void) ml->main_loop_run (ml, g);
5981   guestfs_set_reply_callback (g, NULL, NULL);
5982   if (ctx.cb_sequence != 1) {
5983     error (g, "%s reply failed, see earlier error messages", "guestfs_upload");
5984     guestfs_set_ready (g);
5985     return -1;
5986   }
5987
5988   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UPLOAD, serial) == -1) {
5989     guestfs_set_ready (g);
5990     return -1;
5991   }
5992
5993   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5994     error (g, "%s", ctx.err.error_message);
5995     guestfs_set_ready (g);
5996     return -1;
5997   }
5998
5999   guestfs_set_ready (g);
6000   return 0;
6001 }
6002
6003 struct download_ctx {
6004   /* This flag is set by the callbacks, so we know we've done
6005    * the callbacks as expected, and in the right sequence.
6006    * 0 = not called, 1 = reply_cb called.
6007    */
6008   int cb_sequence;
6009   struct guestfs_message_header hdr;
6010   struct guestfs_message_error err;
6011 };
6012
6013 static void download_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6014 {
6015   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6016   struct download_ctx *ctx = (struct download_ctx *) data;
6017
6018   /* This should definitely not happen. */
6019   if (ctx->cb_sequence != 0) {
6020     ctx->cb_sequence = 9999;
6021     error (g, "%s: internal error: reply callback called twice", "guestfs_download");
6022     return;
6023   }
6024
6025   ml->main_loop_quit (ml, g);
6026
6027   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6028     error (g, "%s: failed to parse reply header", "guestfs_download");
6029     return;
6030   }
6031   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6032     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6033       error (g, "%s: failed to parse reply error", "guestfs_download");
6034       return;
6035     }
6036     goto done;
6037   }
6038  done:
6039   ctx->cb_sequence = 1;
6040 }
6041
6042 int guestfs_download (guestfs_h *g,
6043                 const char *remotefilename,
6044                 const char *filename)
6045 {
6046   struct guestfs_download_args args;
6047   struct download_ctx ctx;
6048   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6049   int serial;
6050
6051   if (check_state (g, "guestfs_download") == -1) return -1;
6052   guestfs_set_busy (g);
6053
6054   memset (&ctx, 0, sizeof ctx);
6055
6056   args.remotefilename = (char *) remotefilename;
6057   serial = guestfs__send_sync (g, GUESTFS_PROC_DOWNLOAD,
6058         (xdrproc_t) xdr_guestfs_download_args, (char *) &args);
6059   if (serial == -1) {
6060     guestfs_set_ready (g);
6061     return -1;
6062   }
6063
6064   guestfs__switch_to_receiving (g);
6065   ctx.cb_sequence = 0;
6066   guestfs_set_reply_callback (g, download_reply_cb, &ctx);
6067   (void) ml->main_loop_run (ml, g);
6068   guestfs_set_reply_callback (g, NULL, NULL);
6069   if (ctx.cb_sequence != 1) {
6070     error (g, "%s reply failed, see earlier error messages", "guestfs_download");
6071     guestfs_set_ready (g);
6072     return -1;
6073   }
6074
6075   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1) {
6076     guestfs_set_ready (g);
6077     return -1;
6078   }
6079
6080   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6081     error (g, "%s", ctx.err.error_message);
6082     guestfs_set_ready (g);
6083     return -1;
6084   }
6085
6086   if (guestfs__receive_file_sync (g, filename) == -1) {
6087     guestfs_set_ready (g);
6088     return -1;
6089   }
6090
6091   guestfs_set_ready (g);
6092   return 0;
6093 }
6094
6095 struct checksum_ctx {
6096   /* This flag is set by the callbacks, so we know we've done
6097    * the callbacks as expected, and in the right sequence.
6098    * 0 = not called, 1 = reply_cb called.
6099    */
6100   int cb_sequence;
6101   struct guestfs_message_header hdr;
6102   struct guestfs_message_error err;
6103   struct guestfs_checksum_ret ret;
6104 };
6105
6106 static void checksum_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6107 {
6108   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6109   struct checksum_ctx *ctx = (struct checksum_ctx *) data;
6110
6111   /* This should definitely not happen. */
6112   if (ctx->cb_sequence != 0) {
6113     ctx->cb_sequence = 9999;
6114     error (g, "%s: internal error: reply callback called twice", "guestfs_checksum");
6115     return;
6116   }
6117
6118   ml->main_loop_quit (ml, g);
6119
6120   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6121     error (g, "%s: failed to parse reply header", "guestfs_checksum");
6122     return;
6123   }
6124   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6125     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6126       error (g, "%s: failed to parse reply error", "guestfs_checksum");
6127       return;
6128     }
6129     goto done;
6130   }
6131   if (!xdr_guestfs_checksum_ret (xdr, &ctx->ret)) {
6132     error (g, "%s: failed to parse reply", "guestfs_checksum");
6133     return;
6134   }
6135  done:
6136   ctx->cb_sequence = 1;
6137 }
6138
6139 char *guestfs_checksum (guestfs_h *g,
6140                 const char *csumtype,
6141                 const char *path)
6142 {
6143   struct guestfs_checksum_args args;
6144   struct checksum_ctx ctx;
6145   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6146   int serial;
6147
6148   if (check_state (g, "guestfs_checksum") == -1) return NULL;
6149   guestfs_set_busy (g);
6150
6151   memset (&ctx, 0, sizeof ctx);
6152
6153   args.csumtype = (char *) csumtype;
6154   args.path = (char *) path;
6155   serial = guestfs__send_sync (g, GUESTFS_PROC_CHECKSUM,
6156         (xdrproc_t) xdr_guestfs_checksum_args, (char *) &args);
6157   if (serial == -1) {
6158     guestfs_set_ready (g);
6159     return NULL;
6160   }
6161
6162   guestfs__switch_to_receiving (g);
6163   ctx.cb_sequence = 0;
6164   guestfs_set_reply_callback (g, checksum_reply_cb, &ctx);
6165   (void) ml->main_loop_run (ml, g);
6166   guestfs_set_reply_callback (g, NULL, NULL);
6167   if (ctx.cb_sequence != 1) {
6168     error (g, "%s reply failed, see earlier error messages", "guestfs_checksum");
6169     guestfs_set_ready (g);
6170     return NULL;
6171   }
6172
6173   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHECKSUM, serial) == -1) {
6174     guestfs_set_ready (g);
6175     return NULL;
6176   }
6177
6178   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6179     error (g, "%s", ctx.err.error_message);
6180     guestfs_set_ready (g);
6181     return NULL;
6182   }
6183
6184   guestfs_set_ready (g);
6185   return ctx.ret.checksum; /* caller will free */
6186 }
6187
6188 struct tar_in_ctx {
6189   /* This flag is set by the callbacks, so we know we've done
6190    * the callbacks as expected, and in the right sequence.
6191    * 0 = not called, 1 = reply_cb called.
6192    */
6193   int cb_sequence;
6194   struct guestfs_message_header hdr;
6195   struct guestfs_message_error err;
6196 };
6197
6198 static void tar_in_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6199 {
6200   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6201   struct tar_in_ctx *ctx = (struct tar_in_ctx *) data;
6202
6203   /* This should definitely not happen. */
6204   if (ctx->cb_sequence != 0) {
6205     ctx->cb_sequence = 9999;
6206     error (g, "%s: internal error: reply callback called twice", "guestfs_tar_in");
6207     return;
6208   }
6209
6210   ml->main_loop_quit (ml, g);
6211
6212   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6213     error (g, "%s: failed to parse reply header", "guestfs_tar_in");
6214     return;
6215   }
6216   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6217     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6218       error (g, "%s: failed to parse reply error", "guestfs_tar_in");
6219       return;
6220     }
6221     goto done;
6222   }
6223  done:
6224   ctx->cb_sequence = 1;
6225 }
6226
6227 int guestfs_tar_in (guestfs_h *g,
6228                 const char *tarfile,
6229                 const char *directory)
6230 {
6231   struct guestfs_tar_in_args args;
6232   struct tar_in_ctx ctx;
6233   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6234   int serial;
6235
6236   if (check_state (g, "guestfs_tar_in") == -1) return -1;
6237   guestfs_set_busy (g);
6238
6239   memset (&ctx, 0, sizeof ctx);
6240
6241   args.directory = (char *) directory;
6242   serial = guestfs__send_sync (g, GUESTFS_PROC_TAR_IN,
6243         (xdrproc_t) xdr_guestfs_tar_in_args, (char *) &args);
6244   if (serial == -1) {
6245     guestfs_set_ready (g);
6246     return -1;
6247   }
6248
6249   {
6250     int r;
6251
6252     r = guestfs__send_file_sync (g, tarfile);
6253     if (r == -1) {
6254       guestfs_set_ready (g);
6255       return -1;
6256     }
6257     if (r == -2) /* daemon cancelled */
6258       goto read_reply;
6259   }
6260
6261  read_reply:
6262   guestfs__switch_to_receiving (g);
6263   ctx.cb_sequence = 0;
6264   guestfs_set_reply_callback (g, tar_in_reply_cb, &ctx);
6265   (void) ml->main_loop_run (ml, g);
6266   guestfs_set_reply_callback (g, NULL, NULL);
6267   if (ctx.cb_sequence != 1) {
6268     error (g, "%s reply failed, see earlier error messages", "guestfs_tar_in");
6269     guestfs_set_ready (g);
6270     return -1;
6271   }
6272
6273   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAR_IN, serial) == -1) {
6274     guestfs_set_ready (g);
6275     return -1;
6276   }
6277
6278   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6279     error (g, "%s", ctx.err.error_message);
6280     guestfs_set_ready (g);
6281     return -1;
6282   }
6283
6284   guestfs_set_ready (g);
6285   return 0;
6286 }
6287
6288 struct tar_out_ctx {
6289   /* This flag is set by the callbacks, so we know we've done
6290    * the callbacks as expected, and in the right sequence.
6291    * 0 = not called, 1 = reply_cb called.
6292    */
6293   int cb_sequence;
6294   struct guestfs_message_header hdr;
6295   struct guestfs_message_error err;
6296 };
6297
6298 static void tar_out_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6299 {
6300   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6301   struct tar_out_ctx *ctx = (struct tar_out_ctx *) data;
6302
6303   /* This should definitely not happen. */
6304   if (ctx->cb_sequence != 0) {
6305     ctx->cb_sequence = 9999;
6306     error (g, "%s: internal error: reply callback called twice", "guestfs_tar_out");
6307     return;
6308   }
6309
6310   ml->main_loop_quit (ml, g);
6311
6312   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6313     error (g, "%s: failed to parse reply header", "guestfs_tar_out");
6314     return;
6315   }
6316   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6317     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6318       error (g, "%s: failed to parse reply error", "guestfs_tar_out");
6319       return;
6320     }
6321     goto done;
6322   }
6323  done:
6324   ctx->cb_sequence = 1;
6325 }
6326
6327 int guestfs_tar_out (guestfs_h *g,
6328                 const char *directory,
6329                 const char *tarfile)
6330 {
6331   struct guestfs_tar_out_args args;
6332   struct tar_out_ctx ctx;
6333   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6334   int serial;
6335
6336   if (check_state (g, "guestfs_tar_out") == -1) return -1;
6337   guestfs_set_busy (g);
6338
6339   memset (&ctx, 0, sizeof ctx);
6340
6341   args.directory = (char *) directory;
6342   serial = guestfs__send_sync (g, GUESTFS_PROC_TAR_OUT,
6343         (xdrproc_t) xdr_guestfs_tar_out_args, (char *) &args);
6344   if (serial == -1) {
6345     guestfs_set_ready (g);
6346     return -1;
6347   }
6348
6349   guestfs__switch_to_receiving (g);
6350   ctx.cb_sequence = 0;
6351   guestfs_set_reply_callback (g, tar_out_reply_cb, &ctx);
6352   (void) ml->main_loop_run (ml, g);
6353   guestfs_set_reply_callback (g, NULL, NULL);
6354   if (ctx.cb_sequence != 1) {
6355     error (g, "%s reply failed, see earlier error messages", "guestfs_tar_out");
6356     guestfs_set_ready (g);
6357     return -1;
6358   }
6359
6360   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAR_OUT, serial) == -1) {
6361     guestfs_set_ready (g);
6362     return -1;
6363   }
6364
6365   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6366     error (g, "%s", ctx.err.error_message);
6367     guestfs_set_ready (g);
6368     return -1;
6369   }
6370
6371   if (guestfs__receive_file_sync (g, tarfile) == -1) {
6372     guestfs_set_ready (g);
6373     return -1;
6374   }
6375
6376   guestfs_set_ready (g);
6377   return 0;
6378 }
6379
6380 struct tgz_in_ctx {
6381   /* This flag is set by the callbacks, so we know we've done
6382    * the callbacks as expected, and in the right sequence.
6383    * 0 = not called, 1 = reply_cb called.
6384    */
6385   int cb_sequence;
6386   struct guestfs_message_header hdr;
6387   struct guestfs_message_error err;
6388 };
6389
6390 static void tgz_in_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6391 {
6392   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6393   struct tgz_in_ctx *ctx = (struct tgz_in_ctx *) data;
6394
6395   /* This should definitely not happen. */
6396   if (ctx->cb_sequence != 0) {
6397     ctx->cb_sequence = 9999;
6398     error (g, "%s: internal error: reply callback called twice", "guestfs_tgz_in");
6399     return;
6400   }
6401
6402   ml->main_loop_quit (ml, g);
6403
6404   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6405     error (g, "%s: failed to parse reply header", "guestfs_tgz_in");
6406     return;
6407   }
6408   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6409     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6410       error (g, "%s: failed to parse reply error", "guestfs_tgz_in");
6411       return;
6412     }
6413     goto done;
6414   }
6415  done:
6416   ctx->cb_sequence = 1;
6417 }
6418
6419 int guestfs_tgz_in (guestfs_h *g,
6420                 const char *tarball,
6421                 const char *directory)
6422 {
6423   struct guestfs_tgz_in_args args;
6424   struct tgz_in_ctx ctx;
6425   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6426   int serial;
6427
6428   if (check_state (g, "guestfs_tgz_in") == -1) return -1;
6429   guestfs_set_busy (g);
6430
6431   memset (&ctx, 0, sizeof ctx);
6432
6433   args.directory = (char *) directory;
6434   serial = guestfs__send_sync (g, GUESTFS_PROC_TGZ_IN,
6435         (xdrproc_t) xdr_guestfs_tgz_in_args, (char *) &args);
6436   if (serial == -1) {
6437     guestfs_set_ready (g);
6438     return -1;
6439   }
6440
6441   {
6442     int r;
6443
6444     r = guestfs__send_file_sync (g, tarball);
6445     if (r == -1) {
6446       guestfs_set_ready (g);
6447       return -1;
6448     }
6449     if (r == -2) /* daemon cancelled */
6450       goto read_reply;
6451   }
6452
6453  read_reply:
6454   guestfs__switch_to_receiving (g);
6455   ctx.cb_sequence = 0;
6456   guestfs_set_reply_callback (g, tgz_in_reply_cb, &ctx);
6457   (void) ml->main_loop_run (ml, g);
6458   guestfs_set_reply_callback (g, NULL, NULL);
6459   if (ctx.cb_sequence != 1) {
6460     error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_in");
6461     guestfs_set_ready (g);
6462     return -1;
6463   }
6464
6465   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TGZ_IN, serial) == -1) {
6466     guestfs_set_ready (g);
6467     return -1;
6468   }
6469
6470   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6471     error (g, "%s", ctx.err.error_message);
6472     guestfs_set_ready (g);
6473     return -1;
6474   }
6475
6476   guestfs_set_ready (g);
6477   return 0;
6478 }
6479
6480 struct tgz_out_ctx {
6481   /* This flag is set by the callbacks, so we know we've done
6482    * the callbacks as expected, and in the right sequence.
6483    * 0 = not called, 1 = reply_cb called.
6484    */
6485   int cb_sequence;
6486   struct guestfs_message_header hdr;
6487   struct guestfs_message_error err;
6488 };
6489
6490 static void tgz_out_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6491 {
6492   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6493   struct tgz_out_ctx *ctx = (struct tgz_out_ctx *) data;
6494
6495   /* This should definitely not happen. */
6496   if (ctx->cb_sequence != 0) {
6497     ctx->cb_sequence = 9999;
6498     error (g, "%s: internal error: reply callback called twice", "guestfs_tgz_out");
6499     return;
6500   }
6501
6502   ml->main_loop_quit (ml, g);
6503
6504   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6505     error (g, "%s: failed to parse reply header", "guestfs_tgz_out");
6506     return;
6507   }
6508   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6509     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6510       error (g, "%s: failed to parse reply error", "guestfs_tgz_out");
6511       return;
6512     }
6513     goto done;
6514   }
6515  done:
6516   ctx->cb_sequence = 1;
6517 }
6518
6519 int guestfs_tgz_out (guestfs_h *g,
6520                 const char *directory,
6521                 const char *tarball)
6522 {
6523   struct guestfs_tgz_out_args args;
6524   struct tgz_out_ctx ctx;
6525   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6526   int serial;
6527
6528   if (check_state (g, "guestfs_tgz_out") == -1) return -1;
6529   guestfs_set_busy (g);
6530
6531   memset (&ctx, 0, sizeof ctx);
6532
6533   args.directory = (char *) directory;
6534   serial = guestfs__send_sync (g, GUESTFS_PROC_TGZ_OUT,
6535         (xdrproc_t) xdr_guestfs_tgz_out_args, (char *) &args);
6536   if (serial == -1) {
6537     guestfs_set_ready (g);
6538     return -1;
6539   }
6540
6541   guestfs__switch_to_receiving (g);
6542   ctx.cb_sequence = 0;
6543   guestfs_set_reply_callback (g, tgz_out_reply_cb, &ctx);
6544   (void) ml->main_loop_run (ml, g);
6545   guestfs_set_reply_callback (g, NULL, NULL);
6546   if (ctx.cb_sequence != 1) {
6547     error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_out");
6548     guestfs_set_ready (g);
6549     return -1;
6550   }
6551
6552   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TGZ_OUT, serial) == -1) {
6553     guestfs_set_ready (g);
6554     return -1;
6555   }
6556
6557   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6558     error (g, "%s", ctx.err.error_message);
6559     guestfs_set_ready (g);
6560     return -1;
6561   }
6562
6563   if (guestfs__receive_file_sync (g, tarball) == -1) {
6564     guestfs_set_ready (g);
6565     return -1;
6566   }
6567
6568   guestfs_set_ready (g);
6569   return 0;
6570 }
6571
6572 struct mount_ro_ctx {
6573   /* This flag is set by the callbacks, so we know we've done
6574    * the callbacks as expected, and in the right sequence.
6575    * 0 = not called, 1 = reply_cb called.
6576    */
6577   int cb_sequence;
6578   struct guestfs_message_header hdr;
6579   struct guestfs_message_error err;
6580 };
6581
6582 static void mount_ro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6583 {
6584   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6585   struct mount_ro_ctx *ctx = (struct mount_ro_ctx *) data;
6586
6587   /* This should definitely not happen. */
6588   if (ctx->cb_sequence != 0) {
6589     ctx->cb_sequence = 9999;
6590     error (g, "%s: internal error: reply callback called twice", "guestfs_mount_ro");
6591     return;
6592   }
6593
6594   ml->main_loop_quit (ml, g);
6595
6596   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6597     error (g, "%s: failed to parse reply header", "guestfs_mount_ro");
6598     return;
6599   }
6600   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6601     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6602       error (g, "%s: failed to parse reply error", "guestfs_mount_ro");
6603       return;
6604     }
6605     goto done;
6606   }
6607  done:
6608   ctx->cb_sequence = 1;
6609 }
6610
6611 int guestfs_mount_ro (guestfs_h *g,
6612                 const char *device,
6613                 const char *mountpoint)
6614 {
6615   struct guestfs_mount_ro_args args;
6616   struct mount_ro_ctx ctx;
6617   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6618   int serial;
6619
6620   if (check_state (g, "guestfs_mount_ro") == -1) return -1;
6621   guestfs_set_busy (g);
6622
6623   memset (&ctx, 0, sizeof ctx);
6624
6625   args.device = (char *) device;
6626   args.mountpoint = (char *) mountpoint;
6627   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_RO,
6628         (xdrproc_t) xdr_guestfs_mount_ro_args, (char *) &args);
6629   if (serial == -1) {
6630     guestfs_set_ready (g);
6631     return -1;
6632   }
6633
6634   guestfs__switch_to_receiving (g);
6635   ctx.cb_sequence = 0;
6636   guestfs_set_reply_callback (g, mount_ro_reply_cb, &ctx);
6637   (void) ml->main_loop_run (ml, g);
6638   guestfs_set_reply_callback (g, NULL, NULL);
6639   if (ctx.cb_sequence != 1) {
6640     error (g, "%s reply failed, see earlier error messages", "guestfs_mount_ro");
6641     guestfs_set_ready (g);
6642     return -1;
6643   }
6644
6645   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_RO, serial) == -1) {
6646     guestfs_set_ready (g);
6647     return -1;
6648   }
6649
6650   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6651     error (g, "%s", ctx.err.error_message);
6652     guestfs_set_ready (g);
6653     return -1;
6654   }
6655
6656   guestfs_set_ready (g);
6657   return 0;
6658 }
6659
6660 struct mount_options_ctx {
6661   /* This flag is set by the callbacks, so we know we've done
6662    * the callbacks as expected, and in the right sequence.
6663    * 0 = not called, 1 = reply_cb called.
6664    */
6665   int cb_sequence;
6666   struct guestfs_message_header hdr;
6667   struct guestfs_message_error err;
6668 };
6669
6670 static void mount_options_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6671 {
6672   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6673   struct mount_options_ctx *ctx = (struct mount_options_ctx *) data;
6674
6675   /* This should definitely not happen. */
6676   if (ctx->cb_sequence != 0) {
6677     ctx->cb_sequence = 9999;
6678     error (g, "%s: internal error: reply callback called twice", "guestfs_mount_options");
6679     return;
6680   }
6681
6682   ml->main_loop_quit (ml, g);
6683
6684   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6685     error (g, "%s: failed to parse reply header", "guestfs_mount_options");
6686     return;
6687   }
6688   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6689     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6690       error (g, "%s: failed to parse reply error", "guestfs_mount_options");
6691       return;
6692     }
6693     goto done;
6694   }
6695  done:
6696   ctx->cb_sequence = 1;
6697 }
6698
6699 int guestfs_mount_options (guestfs_h *g,
6700                 const char *options,
6701                 const char *device,
6702                 const char *mountpoint)
6703 {
6704   struct guestfs_mount_options_args args;
6705   struct mount_options_ctx ctx;
6706   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6707   int serial;
6708
6709   if (check_state (g, "guestfs_mount_options") == -1) return -1;
6710   guestfs_set_busy (g);
6711
6712   memset (&ctx, 0, sizeof ctx);
6713
6714   args.options = (char *) options;
6715   args.device = (char *) device;
6716   args.mountpoint = (char *) mountpoint;
6717   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_OPTIONS,
6718         (xdrproc_t) xdr_guestfs_mount_options_args, (char *) &args);
6719   if (serial == -1) {
6720     guestfs_set_ready (g);
6721     return -1;
6722   }
6723
6724   guestfs__switch_to_receiving (g);
6725   ctx.cb_sequence = 0;
6726   guestfs_set_reply_callback (g, mount_options_reply_cb, &ctx);
6727   (void) ml->main_loop_run (ml, g);
6728   guestfs_set_reply_callback (g, NULL, NULL);
6729   if (ctx.cb_sequence != 1) {
6730     error (g, "%s reply failed, see earlier error messages", "guestfs_mount_options");
6731     guestfs_set_ready (g);
6732     return -1;
6733   }
6734
6735   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_OPTIONS, serial) == -1) {
6736     guestfs_set_ready (g);
6737     return -1;
6738   }
6739
6740   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6741     error (g, "%s", ctx.err.error_message);
6742     guestfs_set_ready (g);
6743     return -1;
6744   }
6745
6746   guestfs_set_ready (g);
6747   return 0;
6748 }
6749
6750 struct mount_vfs_ctx {
6751   /* This flag is set by the callbacks, so we know we've done
6752    * the callbacks as expected, and in the right sequence.
6753    * 0 = not called, 1 = reply_cb called.
6754    */
6755   int cb_sequence;
6756   struct guestfs_message_header hdr;
6757   struct guestfs_message_error err;
6758 };
6759
6760 static void mount_vfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6761 {
6762   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6763   struct mount_vfs_ctx *ctx = (struct mount_vfs_ctx *) data;
6764
6765   /* This should definitely not happen. */
6766   if (ctx->cb_sequence != 0) {
6767     ctx->cb_sequence = 9999;
6768     error (g, "%s: internal error: reply callback called twice", "guestfs_mount_vfs");
6769     return;
6770   }
6771
6772   ml->main_loop_quit (ml, g);
6773
6774   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6775     error (g, "%s: failed to parse reply header", "guestfs_mount_vfs");
6776     return;
6777   }
6778   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6779     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6780       error (g, "%s: failed to parse reply error", "guestfs_mount_vfs");
6781       return;
6782     }
6783     goto done;
6784   }
6785  done:
6786   ctx->cb_sequence = 1;
6787 }
6788
6789 int guestfs_mount_vfs (guestfs_h *g,
6790                 const char *options,
6791                 const char *vfstype,
6792                 const char *device,
6793                 const char *mountpoint)
6794 {
6795   struct guestfs_mount_vfs_args args;
6796   struct mount_vfs_ctx ctx;
6797   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6798   int serial;
6799
6800   if (check_state (g, "guestfs_mount_vfs") == -1) return -1;
6801   guestfs_set_busy (g);
6802
6803   memset (&ctx, 0, sizeof ctx);
6804
6805   args.options = (char *) options;
6806   args.vfstype = (char *) vfstype;
6807   args.device = (char *) device;
6808   args.mountpoint = (char *) mountpoint;
6809   serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_VFS,
6810         (xdrproc_t) xdr_guestfs_mount_vfs_args, (char *) &args);
6811   if (serial == -1) {
6812     guestfs_set_ready (g);
6813     return -1;
6814   }
6815
6816   guestfs__switch_to_receiving (g);
6817   ctx.cb_sequence = 0;
6818   guestfs_set_reply_callback (g, mount_vfs_reply_cb, &ctx);
6819   (void) ml->main_loop_run (ml, g);
6820   guestfs_set_reply_callback (g, NULL, NULL);
6821   if (ctx.cb_sequence != 1) {
6822     error (g, "%s reply failed, see earlier error messages", "guestfs_mount_vfs");
6823     guestfs_set_ready (g);
6824     return -1;
6825   }
6826
6827   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_VFS, serial) == -1) {
6828     guestfs_set_ready (g);
6829     return -1;
6830   }
6831
6832   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6833     error (g, "%s", ctx.err.error_message);
6834     guestfs_set_ready (g);
6835     return -1;
6836   }
6837
6838   guestfs_set_ready (g);
6839   return 0;
6840 }
6841
6842 struct debug_ctx {
6843   /* This flag is set by the callbacks, so we know we've done
6844    * the callbacks as expected, and in the right sequence.
6845    * 0 = not called, 1 = reply_cb called.
6846    */
6847   int cb_sequence;
6848   struct guestfs_message_header hdr;
6849   struct guestfs_message_error err;
6850   struct guestfs_debug_ret ret;
6851 };
6852
6853 static void debug_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6854 {
6855   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6856   struct debug_ctx *ctx = (struct debug_ctx *) data;
6857
6858   /* This should definitely not happen. */
6859   if (ctx->cb_sequence != 0) {
6860     ctx->cb_sequence = 9999;
6861     error (g, "%s: internal error: reply callback called twice", "guestfs_debug");
6862     return;
6863   }
6864
6865   ml->main_loop_quit (ml, g);
6866
6867   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6868     error (g, "%s: failed to parse reply header", "guestfs_debug");
6869     return;
6870   }
6871   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6872     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6873       error (g, "%s: failed to parse reply error", "guestfs_debug");
6874       return;
6875     }
6876     goto done;
6877   }
6878   if (!xdr_guestfs_debug_ret (xdr, &ctx->ret)) {
6879     error (g, "%s: failed to parse reply", "guestfs_debug");
6880     return;
6881   }
6882  done:
6883   ctx->cb_sequence = 1;
6884 }
6885
6886 char *guestfs_debug (guestfs_h *g,
6887                 const char *subcmd,
6888                 char * const* const extraargs)
6889 {
6890   struct guestfs_debug_args args;
6891   struct debug_ctx ctx;
6892   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6893   int serial;
6894
6895   if (check_state (g, "guestfs_debug") == -1) return NULL;
6896   guestfs_set_busy (g);
6897
6898   memset (&ctx, 0, sizeof ctx);
6899
6900   args.subcmd = (char *) subcmd;
6901   args.extraargs.extraargs_val = (char **) extraargs;
6902   for (args.extraargs.extraargs_len = 0; extraargs[args.extraargs.extraargs_len]; args.extraargs.extraargs_len++) ;
6903   serial = guestfs__send_sync (g, GUESTFS_PROC_DEBUG,
6904         (xdrproc_t) xdr_guestfs_debug_args, (char *) &args);
6905   if (serial == -1) {
6906     guestfs_set_ready (g);
6907     return NULL;
6908   }
6909
6910   guestfs__switch_to_receiving (g);
6911   ctx.cb_sequence = 0;
6912   guestfs_set_reply_callback (g, debug_reply_cb, &ctx);
6913   (void) ml->main_loop_run (ml, g);
6914   guestfs_set_reply_callback (g, NULL, NULL);
6915   if (ctx.cb_sequence != 1) {
6916     error (g, "%s reply failed, see earlier error messages", "guestfs_debug");
6917     guestfs_set_ready (g);
6918     return NULL;
6919   }
6920
6921   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DEBUG, serial) == -1) {
6922     guestfs_set_ready (g);
6923     return NULL;
6924   }
6925
6926   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
6927     error (g, "%s", ctx.err.error_message);
6928     guestfs_set_ready (g);
6929     return NULL;
6930   }
6931
6932   guestfs_set_ready (g);
6933   return ctx.ret.result; /* caller will free */
6934 }
6935
6936 struct lvremove_ctx {
6937   /* This flag is set by the callbacks, so we know we've done
6938    * the callbacks as expected, and in the right sequence.
6939    * 0 = not called, 1 = reply_cb called.
6940    */
6941   int cb_sequence;
6942   struct guestfs_message_header hdr;
6943   struct guestfs_message_error err;
6944 };
6945
6946 static void lvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr)
6947 {
6948   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6949   struct lvremove_ctx *ctx = (struct lvremove_ctx *) data;
6950
6951   /* This should definitely not happen. */
6952   if (ctx->cb_sequence != 0) {
6953     ctx->cb_sequence = 9999;
6954     error (g, "%s: internal error: reply callback called twice", "guestfs_lvremove");
6955     return;
6956   }
6957
6958   ml->main_loop_quit (ml, g);
6959
6960   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
6961     error (g, "%s: failed to parse reply header", "guestfs_lvremove");
6962     return;
6963   }
6964   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
6965     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
6966       error (g, "%s: failed to parse reply error", "guestfs_lvremove");
6967       return;
6968     }
6969     goto done;
6970   }
6971  done:
6972   ctx->cb_sequence = 1;
6973 }
6974
6975 int guestfs_lvremove (guestfs_h *g,
6976                 const char *device)
6977 {
6978   struct guestfs_lvremove_args args;
6979   struct lvremove_ctx ctx;
6980   guestfs_main_loop *ml = guestfs_get_main_loop (g);
6981   int serial;
6982
6983   if (check_state (g, "guestfs_lvremove") == -1) return -1;
6984   guestfs_set_busy (g);
6985
6986   memset (&ctx, 0, sizeof ctx);
6987
6988   args.device = (char *) device;
6989   serial = guestfs__send_sync (g, GUESTFS_PROC_LVREMOVE,
6990         (xdrproc_t) xdr_guestfs_lvremove_args, (char *) &args);
6991   if (serial == -1) {
6992     guestfs_set_ready (g);
6993     return -1;
6994   }
6995
6996   guestfs__switch_to_receiving (g);
6997   ctx.cb_sequence = 0;
6998   guestfs_set_reply_callback (g, lvremove_reply_cb, &ctx);
6999   (void) ml->main_loop_run (ml, g);
7000   guestfs_set_reply_callback (g, NULL, NULL);
7001   if (ctx.cb_sequence != 1) {
7002     error (g, "%s reply failed, see earlier error messages", "guestfs_lvremove");
7003     guestfs_set_ready (g);
7004     return -1;
7005   }
7006
7007   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVREMOVE, serial) == -1) {
7008     guestfs_set_ready (g);
7009     return -1;
7010   }
7011
7012   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7013     error (g, "%s", ctx.err.error_message);
7014     guestfs_set_ready (g);
7015     return -1;
7016   }
7017
7018   guestfs_set_ready (g);
7019   return 0;
7020 }
7021
7022 struct vgremove_ctx {
7023   /* This flag is set by the callbacks, so we know we've done
7024    * the callbacks as expected, and in the right sequence.
7025    * 0 = not called, 1 = reply_cb called.
7026    */
7027   int cb_sequence;
7028   struct guestfs_message_header hdr;
7029   struct guestfs_message_error err;
7030 };
7031
7032 static void vgremove_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7033 {
7034   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7035   struct vgremove_ctx *ctx = (struct vgremove_ctx *) data;
7036
7037   /* This should definitely not happen. */
7038   if (ctx->cb_sequence != 0) {
7039     ctx->cb_sequence = 9999;
7040     error (g, "%s: internal error: reply callback called twice", "guestfs_vgremove");
7041     return;
7042   }
7043
7044   ml->main_loop_quit (ml, g);
7045
7046   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7047     error (g, "%s: failed to parse reply header", "guestfs_vgremove");
7048     return;
7049   }
7050   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7051     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7052       error (g, "%s: failed to parse reply error", "guestfs_vgremove");
7053       return;
7054     }
7055     goto done;
7056   }
7057  done:
7058   ctx->cb_sequence = 1;
7059 }
7060
7061 int guestfs_vgremove (guestfs_h *g,
7062                 const char *vgname)
7063 {
7064   struct guestfs_vgremove_args args;
7065   struct vgremove_ctx ctx;
7066   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7067   int serial;
7068
7069   if (check_state (g, "guestfs_vgremove") == -1) return -1;
7070   guestfs_set_busy (g);
7071
7072   memset (&ctx, 0, sizeof ctx);
7073
7074   args.vgname = (char *) vgname;
7075   serial = guestfs__send_sync (g, GUESTFS_PROC_VGREMOVE,
7076         (xdrproc_t) xdr_guestfs_vgremove_args, (char *) &args);
7077   if (serial == -1) {
7078     guestfs_set_ready (g);
7079     return -1;
7080   }
7081
7082   guestfs__switch_to_receiving (g);
7083   ctx.cb_sequence = 0;
7084   guestfs_set_reply_callback (g, vgremove_reply_cb, &ctx);
7085   (void) ml->main_loop_run (ml, g);
7086   guestfs_set_reply_callback (g, NULL, NULL);
7087   if (ctx.cb_sequence != 1) {
7088     error (g, "%s reply failed, see earlier error messages", "guestfs_vgremove");
7089     guestfs_set_ready (g);
7090     return -1;
7091   }
7092
7093   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGREMOVE, serial) == -1) {
7094     guestfs_set_ready (g);
7095     return -1;
7096   }
7097
7098   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7099     error (g, "%s", ctx.err.error_message);
7100     guestfs_set_ready (g);
7101     return -1;
7102   }
7103
7104   guestfs_set_ready (g);
7105   return 0;
7106 }
7107
7108 struct pvremove_ctx {
7109   /* This flag is set by the callbacks, so we know we've done
7110    * the callbacks as expected, and in the right sequence.
7111    * 0 = not called, 1 = reply_cb called.
7112    */
7113   int cb_sequence;
7114   struct guestfs_message_header hdr;
7115   struct guestfs_message_error err;
7116 };
7117
7118 static void pvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7119 {
7120   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7121   struct pvremove_ctx *ctx = (struct pvremove_ctx *) data;
7122
7123   /* This should definitely not happen. */
7124   if (ctx->cb_sequence != 0) {
7125     ctx->cb_sequence = 9999;
7126     error (g, "%s: internal error: reply callback called twice", "guestfs_pvremove");
7127     return;
7128   }
7129
7130   ml->main_loop_quit (ml, g);
7131
7132   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7133     error (g, "%s: failed to parse reply header", "guestfs_pvremove");
7134     return;
7135   }
7136   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7137     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7138       error (g, "%s: failed to parse reply error", "guestfs_pvremove");
7139       return;
7140     }
7141     goto done;
7142   }
7143  done:
7144   ctx->cb_sequence = 1;
7145 }
7146
7147 int guestfs_pvremove (guestfs_h *g,
7148                 const char *device)
7149 {
7150   struct guestfs_pvremove_args args;
7151   struct pvremove_ctx ctx;
7152   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7153   int serial;
7154
7155   if (check_state (g, "guestfs_pvremove") == -1) return -1;
7156   guestfs_set_busy (g);
7157
7158   memset (&ctx, 0, sizeof ctx);
7159
7160   args.device = (char *) device;
7161   serial = guestfs__send_sync (g, GUESTFS_PROC_PVREMOVE,
7162         (xdrproc_t) xdr_guestfs_pvremove_args, (char *) &args);
7163   if (serial == -1) {
7164     guestfs_set_ready (g);
7165     return -1;
7166   }
7167
7168   guestfs__switch_to_receiving (g);
7169   ctx.cb_sequence = 0;
7170   guestfs_set_reply_callback (g, pvremove_reply_cb, &ctx);
7171   (void) ml->main_loop_run (ml, g);
7172   guestfs_set_reply_callback (g, NULL, NULL);
7173   if (ctx.cb_sequence != 1) {
7174     error (g, "%s reply failed, see earlier error messages", "guestfs_pvremove");
7175     guestfs_set_ready (g);
7176     return -1;
7177   }
7178
7179   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVREMOVE, serial) == -1) {
7180     guestfs_set_ready (g);
7181     return -1;
7182   }
7183
7184   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7185     error (g, "%s", ctx.err.error_message);
7186     guestfs_set_ready (g);
7187     return -1;
7188   }
7189
7190   guestfs_set_ready (g);
7191   return 0;
7192 }
7193
7194 struct set_e2label_ctx {
7195   /* This flag is set by the callbacks, so we know we've done
7196    * the callbacks as expected, and in the right sequence.
7197    * 0 = not called, 1 = reply_cb called.
7198    */
7199   int cb_sequence;
7200   struct guestfs_message_header hdr;
7201   struct guestfs_message_error err;
7202 };
7203
7204 static void set_e2label_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7205 {
7206   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7207   struct set_e2label_ctx *ctx = (struct set_e2label_ctx *) data;
7208
7209   /* This should definitely not happen. */
7210   if (ctx->cb_sequence != 0) {
7211     ctx->cb_sequence = 9999;
7212     error (g, "%s: internal error: reply callback called twice", "guestfs_set_e2label");
7213     return;
7214   }
7215
7216   ml->main_loop_quit (ml, g);
7217
7218   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7219     error (g, "%s: failed to parse reply header", "guestfs_set_e2label");
7220     return;
7221   }
7222   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7223     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7224       error (g, "%s: failed to parse reply error", "guestfs_set_e2label");
7225       return;
7226     }
7227     goto done;
7228   }
7229  done:
7230   ctx->cb_sequence = 1;
7231 }
7232
7233 int guestfs_set_e2label (guestfs_h *g,
7234                 const char *device,
7235                 const char *label)
7236 {
7237   struct guestfs_set_e2label_args args;
7238   struct set_e2label_ctx ctx;
7239   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7240   int serial;
7241
7242   if (check_state (g, "guestfs_set_e2label") == -1) return -1;
7243   guestfs_set_busy (g);
7244
7245   memset (&ctx, 0, sizeof ctx);
7246
7247   args.device = (char *) device;
7248   args.label = (char *) label;
7249   serial = guestfs__send_sync (g, GUESTFS_PROC_SET_E2LABEL,
7250         (xdrproc_t) xdr_guestfs_set_e2label_args, (char *) &args);
7251   if (serial == -1) {
7252     guestfs_set_ready (g);
7253     return -1;
7254   }
7255
7256   guestfs__switch_to_receiving (g);
7257   ctx.cb_sequence = 0;
7258   guestfs_set_reply_callback (g, set_e2label_reply_cb, &ctx);
7259   (void) ml->main_loop_run (ml, g);
7260   guestfs_set_reply_callback (g, NULL, NULL);
7261   if (ctx.cb_sequence != 1) {
7262     error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2label");
7263     guestfs_set_ready (g);
7264     return -1;
7265   }
7266
7267   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SET_E2LABEL, serial) == -1) {
7268     guestfs_set_ready (g);
7269     return -1;
7270   }
7271
7272   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7273     error (g, "%s", ctx.err.error_message);
7274     guestfs_set_ready (g);
7275     return -1;
7276   }
7277
7278   guestfs_set_ready (g);
7279   return 0;
7280 }
7281
7282 struct get_e2label_ctx {
7283   /* This flag is set by the callbacks, so we know we've done
7284    * the callbacks as expected, and in the right sequence.
7285    * 0 = not called, 1 = reply_cb called.
7286    */
7287   int cb_sequence;
7288   struct guestfs_message_header hdr;
7289   struct guestfs_message_error err;
7290   struct guestfs_get_e2label_ret ret;
7291 };
7292
7293 static void get_e2label_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7294 {
7295   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7296   struct get_e2label_ctx *ctx = (struct get_e2label_ctx *) data;
7297
7298   /* This should definitely not happen. */
7299   if (ctx->cb_sequence != 0) {
7300     ctx->cb_sequence = 9999;
7301     error (g, "%s: internal error: reply callback called twice", "guestfs_get_e2label");
7302     return;
7303   }
7304
7305   ml->main_loop_quit (ml, g);
7306
7307   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7308     error (g, "%s: failed to parse reply header", "guestfs_get_e2label");
7309     return;
7310   }
7311   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7312     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7313       error (g, "%s: failed to parse reply error", "guestfs_get_e2label");
7314       return;
7315     }
7316     goto done;
7317   }
7318   if (!xdr_guestfs_get_e2label_ret (xdr, &ctx->ret)) {
7319     error (g, "%s: failed to parse reply", "guestfs_get_e2label");
7320     return;
7321   }
7322  done:
7323   ctx->cb_sequence = 1;
7324 }
7325
7326 char *guestfs_get_e2label (guestfs_h *g,
7327                 const char *device)
7328 {
7329   struct guestfs_get_e2label_args args;
7330   struct get_e2label_ctx ctx;
7331   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7332   int serial;
7333
7334   if (check_state (g, "guestfs_get_e2label") == -1) return NULL;
7335   guestfs_set_busy (g);
7336
7337   memset (&ctx, 0, sizeof ctx);
7338
7339   args.device = (char *) device;
7340   serial = guestfs__send_sync (g, GUESTFS_PROC_GET_E2LABEL,
7341         (xdrproc_t) xdr_guestfs_get_e2label_args, (char *) &args);
7342   if (serial == -1) {
7343     guestfs_set_ready (g);
7344     return NULL;
7345   }
7346
7347   guestfs__switch_to_receiving (g);
7348   ctx.cb_sequence = 0;
7349   guestfs_set_reply_callback (g, get_e2label_reply_cb, &ctx);
7350   (void) ml->main_loop_run (ml, g);
7351   guestfs_set_reply_callback (g, NULL, NULL);
7352   if (ctx.cb_sequence != 1) {
7353     error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2label");
7354     guestfs_set_ready (g);
7355     return NULL;
7356   }
7357
7358   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GET_E2LABEL, serial) == -1) {
7359     guestfs_set_ready (g);
7360     return NULL;
7361   }
7362
7363   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7364     error (g, "%s", ctx.err.error_message);
7365     guestfs_set_ready (g);
7366     return NULL;
7367   }
7368
7369   guestfs_set_ready (g);
7370   return ctx.ret.label; /* caller will free */
7371 }
7372
7373 struct set_e2uuid_ctx {
7374   /* This flag is set by the callbacks, so we know we've done
7375    * the callbacks as expected, and in the right sequence.
7376    * 0 = not called, 1 = reply_cb called.
7377    */
7378   int cb_sequence;
7379   struct guestfs_message_header hdr;
7380   struct guestfs_message_error err;
7381 };
7382
7383 static void set_e2uuid_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7384 {
7385   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7386   struct set_e2uuid_ctx *ctx = (struct set_e2uuid_ctx *) data;
7387
7388   /* This should definitely not happen. */
7389   if (ctx->cb_sequence != 0) {
7390     ctx->cb_sequence = 9999;
7391     error (g, "%s: internal error: reply callback called twice", "guestfs_set_e2uuid");
7392     return;
7393   }
7394
7395   ml->main_loop_quit (ml, g);
7396
7397   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7398     error (g, "%s: failed to parse reply header", "guestfs_set_e2uuid");
7399     return;
7400   }
7401   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7402     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7403       error (g, "%s: failed to parse reply error", "guestfs_set_e2uuid");
7404       return;
7405     }
7406     goto done;
7407   }
7408  done:
7409   ctx->cb_sequence = 1;
7410 }
7411
7412 int guestfs_set_e2uuid (guestfs_h *g,
7413                 const char *device,
7414                 const char *uuid)
7415 {
7416   struct guestfs_set_e2uuid_args args;
7417   struct set_e2uuid_ctx ctx;
7418   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7419   int serial;
7420
7421   if (check_state (g, "guestfs_set_e2uuid") == -1) return -1;
7422   guestfs_set_busy (g);
7423
7424   memset (&ctx, 0, sizeof ctx);
7425
7426   args.device = (char *) device;
7427   args.uuid = (char *) uuid;
7428   serial = guestfs__send_sync (g, GUESTFS_PROC_SET_E2UUID,
7429         (xdrproc_t) xdr_guestfs_set_e2uuid_args, (char *) &args);
7430   if (serial == -1) {
7431     guestfs_set_ready (g);
7432     return -1;
7433   }
7434
7435   guestfs__switch_to_receiving (g);
7436   ctx.cb_sequence = 0;
7437   guestfs_set_reply_callback (g, set_e2uuid_reply_cb, &ctx);
7438   (void) ml->main_loop_run (ml, g);
7439   guestfs_set_reply_callback (g, NULL, NULL);
7440   if (ctx.cb_sequence != 1) {
7441     error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2uuid");
7442     guestfs_set_ready (g);
7443     return -1;
7444   }
7445
7446   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SET_E2UUID, serial) == -1) {
7447     guestfs_set_ready (g);
7448     return -1;
7449   }
7450
7451   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7452     error (g, "%s", ctx.err.error_message);
7453     guestfs_set_ready (g);
7454     return -1;
7455   }
7456
7457   guestfs_set_ready (g);
7458   return 0;
7459 }
7460
7461 struct get_e2uuid_ctx {
7462   /* This flag is set by the callbacks, so we know we've done
7463    * the callbacks as expected, and in the right sequence.
7464    * 0 = not called, 1 = reply_cb called.
7465    */
7466   int cb_sequence;
7467   struct guestfs_message_header hdr;
7468   struct guestfs_message_error err;
7469   struct guestfs_get_e2uuid_ret ret;
7470 };
7471
7472 static void get_e2uuid_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7473 {
7474   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7475   struct get_e2uuid_ctx *ctx = (struct get_e2uuid_ctx *) data;
7476
7477   /* This should definitely not happen. */
7478   if (ctx->cb_sequence != 0) {
7479     ctx->cb_sequence = 9999;
7480     error (g, "%s: internal error: reply callback called twice", "guestfs_get_e2uuid");
7481     return;
7482   }
7483
7484   ml->main_loop_quit (ml, g);
7485
7486   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7487     error (g, "%s: failed to parse reply header", "guestfs_get_e2uuid");
7488     return;
7489   }
7490   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7491     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7492       error (g, "%s: failed to parse reply error", "guestfs_get_e2uuid");
7493       return;
7494     }
7495     goto done;
7496   }
7497   if (!xdr_guestfs_get_e2uuid_ret (xdr, &ctx->ret)) {
7498     error (g, "%s: failed to parse reply", "guestfs_get_e2uuid");
7499     return;
7500   }
7501  done:
7502   ctx->cb_sequence = 1;
7503 }
7504
7505 char *guestfs_get_e2uuid (guestfs_h *g,
7506                 const char *device)
7507 {
7508   struct guestfs_get_e2uuid_args args;
7509   struct get_e2uuid_ctx ctx;
7510   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7511   int serial;
7512
7513   if (check_state (g, "guestfs_get_e2uuid") == -1) return NULL;
7514   guestfs_set_busy (g);
7515
7516   memset (&ctx, 0, sizeof ctx);
7517
7518   args.device = (char *) device;
7519   serial = guestfs__send_sync (g, GUESTFS_PROC_GET_E2UUID,
7520         (xdrproc_t) xdr_guestfs_get_e2uuid_args, (char *) &args);
7521   if (serial == -1) {
7522     guestfs_set_ready (g);
7523     return NULL;
7524   }
7525
7526   guestfs__switch_to_receiving (g);
7527   ctx.cb_sequence = 0;
7528   guestfs_set_reply_callback (g, get_e2uuid_reply_cb, &ctx);
7529   (void) ml->main_loop_run (ml, g);
7530   guestfs_set_reply_callback (g, NULL, NULL);
7531   if (ctx.cb_sequence != 1) {
7532     error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2uuid");
7533     guestfs_set_ready (g);
7534     return NULL;
7535   }
7536
7537   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GET_E2UUID, serial) == -1) {
7538     guestfs_set_ready (g);
7539     return NULL;
7540   }
7541
7542   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7543     error (g, "%s", ctx.err.error_message);
7544     guestfs_set_ready (g);
7545     return NULL;
7546   }
7547
7548   guestfs_set_ready (g);
7549   return ctx.ret.uuid; /* caller will free */
7550 }
7551
7552 struct fsck_ctx {
7553   /* This flag is set by the callbacks, so we know we've done
7554    * the callbacks as expected, and in the right sequence.
7555    * 0 = not called, 1 = reply_cb called.
7556    */
7557   int cb_sequence;
7558   struct guestfs_message_header hdr;
7559   struct guestfs_message_error err;
7560   struct guestfs_fsck_ret ret;
7561 };
7562
7563 static void fsck_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7564 {
7565   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7566   struct fsck_ctx *ctx = (struct fsck_ctx *) data;
7567
7568   /* This should definitely not happen. */
7569   if (ctx->cb_sequence != 0) {
7570     ctx->cb_sequence = 9999;
7571     error (g, "%s: internal error: reply callback called twice", "guestfs_fsck");
7572     return;
7573   }
7574
7575   ml->main_loop_quit (ml, g);
7576
7577   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7578     error (g, "%s: failed to parse reply header", "guestfs_fsck");
7579     return;
7580   }
7581   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7582     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7583       error (g, "%s: failed to parse reply error", "guestfs_fsck");
7584       return;
7585     }
7586     goto done;
7587   }
7588   if (!xdr_guestfs_fsck_ret (xdr, &ctx->ret)) {
7589     error (g, "%s: failed to parse reply", "guestfs_fsck");
7590     return;
7591   }
7592  done:
7593   ctx->cb_sequence = 1;
7594 }
7595
7596 int guestfs_fsck (guestfs_h *g,
7597                 const char *fstype,
7598                 const char *device)
7599 {
7600   struct guestfs_fsck_args args;
7601   struct fsck_ctx ctx;
7602   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7603   int serial;
7604
7605   if (check_state (g, "guestfs_fsck") == -1) return -1;
7606   guestfs_set_busy (g);
7607
7608   memset (&ctx, 0, sizeof ctx);
7609
7610   args.fstype = (char *) fstype;
7611   args.device = (char *) device;
7612   serial = guestfs__send_sync (g, GUESTFS_PROC_FSCK,
7613         (xdrproc_t) xdr_guestfs_fsck_args, (char *) &args);
7614   if (serial == -1) {
7615     guestfs_set_ready (g);
7616     return -1;
7617   }
7618
7619   guestfs__switch_to_receiving (g);
7620   ctx.cb_sequence = 0;
7621   guestfs_set_reply_callback (g, fsck_reply_cb, &ctx);
7622   (void) ml->main_loop_run (ml, g);
7623   guestfs_set_reply_callback (g, NULL, NULL);
7624   if (ctx.cb_sequence != 1) {
7625     error (g, "%s reply failed, see earlier error messages", "guestfs_fsck");
7626     guestfs_set_ready (g);
7627     return -1;
7628   }
7629
7630   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FSCK, serial) == -1) {
7631     guestfs_set_ready (g);
7632     return -1;
7633   }
7634
7635   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7636     error (g, "%s", ctx.err.error_message);
7637     guestfs_set_ready (g);
7638     return -1;
7639   }
7640
7641   guestfs_set_ready (g);
7642   return ctx.ret.status;
7643 }
7644
7645 struct zero_ctx {
7646   /* This flag is set by the callbacks, so we know we've done
7647    * the callbacks as expected, and in the right sequence.
7648    * 0 = not called, 1 = reply_cb called.
7649    */
7650   int cb_sequence;
7651   struct guestfs_message_header hdr;
7652   struct guestfs_message_error err;
7653 };
7654
7655 static void zero_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7656 {
7657   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7658   struct zero_ctx *ctx = (struct zero_ctx *) data;
7659
7660   /* This should definitely not happen. */
7661   if (ctx->cb_sequence != 0) {
7662     ctx->cb_sequence = 9999;
7663     error (g, "%s: internal error: reply callback called twice", "guestfs_zero");
7664     return;
7665   }
7666
7667   ml->main_loop_quit (ml, g);
7668
7669   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7670     error (g, "%s: failed to parse reply header", "guestfs_zero");
7671     return;
7672   }
7673   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7674     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7675       error (g, "%s: failed to parse reply error", "guestfs_zero");
7676       return;
7677     }
7678     goto done;
7679   }
7680  done:
7681   ctx->cb_sequence = 1;
7682 }
7683
7684 int guestfs_zero (guestfs_h *g,
7685                 const char *device)
7686 {
7687   struct guestfs_zero_args args;
7688   struct zero_ctx ctx;
7689   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7690   int serial;
7691
7692   if (check_state (g, "guestfs_zero") == -1) return -1;
7693   guestfs_set_busy (g);
7694
7695   memset (&ctx, 0, sizeof ctx);
7696
7697   args.device = (char *) device;
7698   serial = guestfs__send_sync (g, GUESTFS_PROC_ZERO,
7699         (xdrproc_t) xdr_guestfs_zero_args, (char *) &args);
7700   if (serial == -1) {
7701     guestfs_set_ready (g);
7702     return -1;
7703   }
7704
7705   guestfs__switch_to_receiving (g);
7706   ctx.cb_sequence = 0;
7707   guestfs_set_reply_callback (g, zero_reply_cb, &ctx);
7708   (void) ml->main_loop_run (ml, g);
7709   guestfs_set_reply_callback (g, NULL, NULL);
7710   if (ctx.cb_sequence != 1) {
7711     error (g, "%s reply failed, see earlier error messages", "guestfs_zero");
7712     guestfs_set_ready (g);
7713     return -1;
7714   }
7715
7716   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_ZERO, serial) == -1) {
7717     guestfs_set_ready (g);
7718     return -1;
7719   }
7720
7721   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7722     error (g, "%s", ctx.err.error_message);
7723     guestfs_set_ready (g);
7724     return -1;
7725   }
7726
7727   guestfs_set_ready (g);
7728   return 0;
7729 }
7730
7731 struct grub_install_ctx {
7732   /* This flag is set by the callbacks, so we know we've done
7733    * the callbacks as expected, and in the right sequence.
7734    * 0 = not called, 1 = reply_cb called.
7735    */
7736   int cb_sequence;
7737   struct guestfs_message_header hdr;
7738   struct guestfs_message_error err;
7739 };
7740
7741 static void grub_install_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7742 {
7743   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7744   struct grub_install_ctx *ctx = (struct grub_install_ctx *) data;
7745
7746   /* This should definitely not happen. */
7747   if (ctx->cb_sequence != 0) {
7748     ctx->cb_sequence = 9999;
7749     error (g, "%s: internal error: reply callback called twice", "guestfs_grub_install");
7750     return;
7751   }
7752
7753   ml->main_loop_quit (ml, g);
7754
7755   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7756     error (g, "%s: failed to parse reply header", "guestfs_grub_install");
7757     return;
7758   }
7759   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7760     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7761       error (g, "%s: failed to parse reply error", "guestfs_grub_install");
7762       return;
7763     }
7764     goto done;
7765   }
7766  done:
7767   ctx->cb_sequence = 1;
7768 }
7769
7770 int guestfs_grub_install (guestfs_h *g,
7771                 const char *root,
7772                 const char *device)
7773 {
7774   struct guestfs_grub_install_args args;
7775   struct grub_install_ctx ctx;
7776   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7777   int serial;
7778
7779   if (check_state (g, "guestfs_grub_install") == -1) return -1;
7780   guestfs_set_busy (g);
7781
7782   memset (&ctx, 0, sizeof ctx);
7783
7784   args.root = (char *) root;
7785   args.device = (char *) device;
7786   serial = guestfs__send_sync (g, GUESTFS_PROC_GRUB_INSTALL,
7787         (xdrproc_t) xdr_guestfs_grub_install_args, (char *) &args);
7788   if (serial == -1) {
7789     guestfs_set_ready (g);
7790     return -1;
7791   }
7792
7793   guestfs__switch_to_receiving (g);
7794   ctx.cb_sequence = 0;
7795   guestfs_set_reply_callback (g, grub_install_reply_cb, &ctx);
7796   (void) ml->main_loop_run (ml, g);
7797   guestfs_set_reply_callback (g, NULL, NULL);
7798   if (ctx.cb_sequence != 1) {
7799     error (g, "%s reply failed, see earlier error messages", "guestfs_grub_install");
7800     guestfs_set_ready (g);
7801     return -1;
7802   }
7803
7804   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GRUB_INSTALL, serial) == -1) {
7805     guestfs_set_ready (g);
7806     return -1;
7807   }
7808
7809   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7810     error (g, "%s", ctx.err.error_message);
7811     guestfs_set_ready (g);
7812     return -1;
7813   }
7814
7815   guestfs_set_ready (g);
7816   return 0;
7817 }
7818
7819 struct cp_ctx {
7820   /* This flag is set by the callbacks, so we know we've done
7821    * the callbacks as expected, and in the right sequence.
7822    * 0 = not called, 1 = reply_cb called.
7823    */
7824   int cb_sequence;
7825   struct guestfs_message_header hdr;
7826   struct guestfs_message_error err;
7827 };
7828
7829 static void cp_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7830 {
7831   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7832   struct cp_ctx *ctx = (struct cp_ctx *) data;
7833
7834   /* This should definitely not happen. */
7835   if (ctx->cb_sequence != 0) {
7836     ctx->cb_sequence = 9999;
7837     error (g, "%s: internal error: reply callback called twice", "guestfs_cp");
7838     return;
7839   }
7840
7841   ml->main_loop_quit (ml, g);
7842
7843   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7844     error (g, "%s: failed to parse reply header", "guestfs_cp");
7845     return;
7846   }
7847   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7848     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7849       error (g, "%s: failed to parse reply error", "guestfs_cp");
7850       return;
7851     }
7852     goto done;
7853   }
7854  done:
7855   ctx->cb_sequence = 1;
7856 }
7857
7858 int guestfs_cp (guestfs_h *g,
7859                 const char *src,
7860                 const char *dest)
7861 {
7862   struct guestfs_cp_args args;
7863   struct cp_ctx ctx;
7864   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7865   int serial;
7866
7867   if (check_state (g, "guestfs_cp") == -1) return -1;
7868   guestfs_set_busy (g);
7869
7870   memset (&ctx, 0, sizeof ctx);
7871
7872   args.src = (char *) src;
7873   args.dest = (char *) dest;
7874   serial = guestfs__send_sync (g, GUESTFS_PROC_CP,
7875         (xdrproc_t) xdr_guestfs_cp_args, (char *) &args);
7876   if (serial == -1) {
7877     guestfs_set_ready (g);
7878     return -1;
7879   }
7880
7881   guestfs__switch_to_receiving (g);
7882   ctx.cb_sequence = 0;
7883   guestfs_set_reply_callback (g, cp_reply_cb, &ctx);
7884   (void) ml->main_loop_run (ml, g);
7885   guestfs_set_reply_callback (g, NULL, NULL);
7886   if (ctx.cb_sequence != 1) {
7887     error (g, "%s reply failed, see earlier error messages", "guestfs_cp");
7888     guestfs_set_ready (g);
7889     return -1;
7890   }
7891
7892   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CP, serial) == -1) {
7893     guestfs_set_ready (g);
7894     return -1;
7895   }
7896
7897   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7898     error (g, "%s", ctx.err.error_message);
7899     guestfs_set_ready (g);
7900     return -1;
7901   }
7902
7903   guestfs_set_ready (g);
7904   return 0;
7905 }
7906
7907 struct cp_a_ctx {
7908   /* This flag is set by the callbacks, so we know we've done
7909    * the callbacks as expected, and in the right sequence.
7910    * 0 = not called, 1 = reply_cb called.
7911    */
7912   int cb_sequence;
7913   struct guestfs_message_header hdr;
7914   struct guestfs_message_error err;
7915 };
7916
7917 static void cp_a_reply_cb (guestfs_h *g, void *data, XDR *xdr)
7918 {
7919   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7920   struct cp_a_ctx *ctx = (struct cp_a_ctx *) data;
7921
7922   /* This should definitely not happen. */
7923   if (ctx->cb_sequence != 0) {
7924     ctx->cb_sequence = 9999;
7925     error (g, "%s: internal error: reply callback called twice", "guestfs_cp_a");
7926     return;
7927   }
7928
7929   ml->main_loop_quit (ml, g);
7930
7931   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
7932     error (g, "%s: failed to parse reply header", "guestfs_cp_a");
7933     return;
7934   }
7935   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
7936     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
7937       error (g, "%s: failed to parse reply error", "guestfs_cp_a");
7938       return;
7939     }
7940     goto done;
7941   }
7942  done:
7943   ctx->cb_sequence = 1;
7944 }
7945
7946 int guestfs_cp_a (guestfs_h *g,
7947                 const char *src,
7948                 const char *dest)
7949 {
7950   struct guestfs_cp_a_args args;
7951   struct cp_a_ctx ctx;
7952   guestfs_main_loop *ml = guestfs_get_main_loop (g);
7953   int serial;
7954
7955   if (check_state (g, "guestfs_cp_a") == -1) return -1;
7956   guestfs_set_busy (g);
7957
7958   memset (&ctx, 0, sizeof ctx);
7959
7960   args.src = (char *) src;
7961   args.dest = (char *) dest;
7962   serial = guestfs__send_sync (g, GUESTFS_PROC_CP_A,
7963         (xdrproc_t) xdr_guestfs_cp_a_args, (char *) &args);
7964   if (serial == -1) {
7965     guestfs_set_ready (g);
7966     return -1;
7967   }
7968
7969   guestfs__switch_to_receiving (g);
7970   ctx.cb_sequence = 0;
7971   guestfs_set_reply_callback (g, cp_a_reply_cb, &ctx);
7972   (void) ml->main_loop_run (ml, g);
7973   guestfs_set_reply_callback (g, NULL, NULL);
7974   if (ctx.cb_sequence != 1) {
7975     error (g, "%s reply failed, see earlier error messages", "guestfs_cp_a");
7976     guestfs_set_ready (g);
7977     return -1;
7978   }
7979
7980   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CP_A, serial) == -1) {
7981     guestfs_set_ready (g);
7982     return -1;
7983   }
7984
7985   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
7986     error (g, "%s", ctx.err.error_message);
7987     guestfs_set_ready (g);
7988     return -1;
7989   }
7990
7991   guestfs_set_ready (g);
7992   return 0;
7993 }
7994
7995 struct mv_ctx {
7996   /* This flag is set by the callbacks, so we know we've done
7997    * the callbacks as expected, and in the right sequence.
7998    * 0 = not called, 1 = reply_cb called.
7999    */
8000   int cb_sequence;
8001   struct guestfs_message_header hdr;
8002   struct guestfs_message_error err;
8003 };
8004
8005 static void mv_reply_cb (guestfs_h *g, void *data, XDR *xdr)
8006 {
8007   guestfs_main_loop *ml = guestfs_get_main_loop (g);
8008   struct mv_ctx *ctx = (struct mv_ctx *) data;
8009
8010   /* This should definitely not happen. */
8011   if (ctx->cb_sequence != 0) {
8012     ctx->cb_sequence = 9999;
8013     error (g, "%s: internal error: reply callback called twice", "guestfs_mv");
8014     return;
8015   }
8016
8017   ml->main_loop_quit (ml, g);
8018
8019   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
8020     error (g, "%s: failed to parse reply header", "guestfs_mv");
8021     return;
8022   }
8023   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
8024     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
8025       error (g, "%s: failed to parse reply error", "guestfs_mv");
8026       return;
8027     }
8028     goto done;
8029   }
8030  done:
8031   ctx->cb_sequence = 1;
8032 }
8033
8034 int guestfs_mv (guestfs_h *g,
8035                 const char *src,
8036                 const char *dest)
8037 {
8038   struct guestfs_mv_args args;
8039   struct mv_ctx ctx;
8040   guestfs_main_loop *ml = guestfs_get_main_loop (g);
8041   int serial;
8042
8043   if (check_state (g, "guestfs_mv") == -1) return -1;
8044   guestfs_set_busy (g);
8045
8046   memset (&ctx, 0, sizeof ctx);
8047
8048   args.src = (char *) src;
8049   args.dest = (char *) dest;
8050   serial = guestfs__send_sync (g, GUESTFS_PROC_MV,
8051         (xdrproc_t) xdr_guestfs_mv_args, (char *) &args);
8052   if (serial == -1) {
8053     guestfs_set_ready (g);
8054     return -1;
8055   }
8056
8057   guestfs__switch_to_receiving (g);
8058   ctx.cb_sequence = 0;
8059   guestfs_set_reply_callback (g, mv_reply_cb, &ctx);
8060   (void) ml->main_loop_run (ml, g);
8061   guestfs_set_reply_callback (g, NULL, NULL);
8062   if (ctx.cb_sequence != 1) {
8063     error (g, "%s reply failed, see earlier error messages", "guestfs_mv");
8064     guestfs_set_ready (g);
8065     return -1;
8066   }
8067
8068   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MV, serial) == -1) {
8069     guestfs_set_ready (g);
8070     return -1;
8071   }
8072
8073   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
8074     error (g, "%s", ctx.err.error_message);
8075     guestfs_set_ready (g);
8076     return -1;
8077   }
8078
8079   guestfs_set_ready (g);
8080   return 0;
8081 }
8082
8083 struct drop_caches_ctx {
8084   /* This flag is set by the callbacks, so we know we've done
8085    * the callbacks as expected, and in the right sequence.
8086    * 0 = not called, 1 = reply_cb called.
8087    */
8088   int cb_sequence;
8089   struct guestfs_message_header hdr;
8090   struct guestfs_message_error err;
8091 };
8092
8093 static void drop_caches_reply_cb (guestfs_h *g, void *data, XDR *xdr)
8094 {
8095   guestfs_main_loop *ml = guestfs_get_main_loop (g);
8096   struct drop_caches_ctx *ctx = (struct drop_caches_ctx *) data;
8097
8098   /* This should definitely not happen. */
8099   if (ctx->cb_sequence != 0) {
8100     ctx->cb_sequence = 9999;
8101     error (g, "%s: internal error: reply callback called twice", "guestfs_drop_caches");
8102     return;
8103   }
8104
8105   ml->main_loop_quit (ml, g);
8106
8107   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
8108     error (g, "%s: failed to parse reply header", "guestfs_drop_caches");
8109     return;
8110   }
8111   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
8112     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
8113       error (g, "%s: failed to parse reply error", "guestfs_drop_caches");
8114       return;
8115     }
8116     goto done;
8117   }
8118  done:
8119   ctx->cb_sequence = 1;
8120 }
8121
8122 int guestfs_drop_caches (guestfs_h *g,
8123                 int whattodrop)
8124 {
8125   struct guestfs_drop_caches_args args;
8126   struct drop_caches_ctx ctx;
8127   guestfs_main_loop *ml = guestfs_get_main_loop (g);
8128   int serial;
8129
8130   if (check_state (g, "guestfs_drop_caches") == -1) return -1;
8131   guestfs_set_busy (g);
8132
8133   memset (&ctx, 0, sizeof ctx);
8134
8135   args.whattodrop = whattodrop;
8136   serial = guestfs__send_sync (g, GUESTFS_PROC_DROP_CACHES,
8137         (xdrproc_t) xdr_guestfs_drop_caches_args, (char *) &args);
8138   if (serial == -1) {
8139     guestfs_set_ready (g);
8140     return -1;
8141   }
8142
8143   guestfs__switch_to_receiving (g);
8144   ctx.cb_sequence = 0;
8145   guestfs_set_reply_callback (g, drop_caches_reply_cb, &ctx);
8146   (void) ml->main_loop_run (ml, g);
8147   guestfs_set_reply_callback (g, NULL, NULL);
8148   if (ctx.cb_sequence != 1) {
8149     error (g, "%s reply failed, see earlier error messages", "guestfs_drop_caches");
8150     guestfs_set_ready (g);
8151     return -1;
8152   }
8153
8154   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DROP_CACHES, serial) == -1) {
8155     guestfs_set_ready (g);
8156     return -1;
8157   }
8158
8159   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
8160     error (g, "%s", ctx.err.error_message);
8161     guestfs_set_ready (g);
8162     return -1;
8163   }
8164
8165   guestfs_set_ready (g);
8166   return 0;
8167 }
8168