Generated code for head/tail commands.
[libguestfs.git] / src / guestfs-actions.c
1 /* libguestfs generated file
2  * WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
3  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
4  *
5  * Copyright (C) 2009 Red Hat Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "guestfs.h"
26 #include "guestfs_protocol.h"
27
28 #define error guestfs_error
29 #define perrorf guestfs_perrorf
30 #define safe_malloc guestfs_safe_malloc
31 #define safe_realloc guestfs_safe_realloc
32 #define safe_strdup guestfs_safe_strdup
33 #define safe_memdup guestfs_safe_memdup
34
35 /* Check the return message from a call for validity. */
36 static int
37 check_reply_header (guestfs_h *g,
38                     const struct guestfs_message_header *hdr,
39                     int proc_nr, int serial)
40 {
41   if (hdr->prog != GUESTFS_PROGRAM) {
42     error (g, "wrong program (%d/%d)", hdr->prog, GUESTFS_PROGRAM);
43     return -1;
44   }
45   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
46     error (g, "wrong protocol version (%d/%d)",
47            hdr->vers, GUESTFS_PROTOCOL_VERSION);
48     return -1;
49   }
50   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
51     error (g, "unexpected message direction (%d/%d)",
52            hdr->direction, GUESTFS_DIRECTION_REPLY);
53     return -1;
54   }
55   if (hdr->proc != proc_nr) {
56     error (g, "unexpected procedure number (%d/%d)", hdr->proc, proc_nr);
57     return -1;
58   }
59   if (hdr->serial != serial) {
60     error (g, "unexpected serial (%d/%d)", hdr->serial, serial);
61     return -1;
62   }
63
64   return 0;
65 }
66
67 /* Check we are in the right state to run a high-level action. */
68 static int
69 check_state (guestfs_h *g, const char *caller)
70 {
71   if (!guestfs_is_ready (g)) {
72     if (guestfs_is_config (g))
73       error (g, "%s: call launch() before using this function",
74         caller);
75     else if (guestfs_is_launching (g))
76       error (g, "%s: call wait_ready() before using this function",
77         caller);
78     else
79       error (g, "%s called from the wrong state, %d != READY",
80         caller, guestfs_get_state (g));
81     return -1;
82   }
83   return 0;
84 }
85
86 struct mount_ctx {
87   /* This flag is set by the callbacks, so we know we've done
88    * the callbacks as expected, and in the right sequence.
89    * 0 = not called, 1 = 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_end_busy (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_end_busy (g);
156     return -1;
157   }
158
159   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT, serial) == -1) {
160     guestfs_end_busy (g);
161     return -1;
162   }
163
164   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
165     error (g, "%s", ctx.err.error_message);
166     free (ctx.err.error_message);
167     guestfs_end_busy (g);
168     return -1;
169   }
170
171   guestfs_end_busy (g);
172   return 0;
173 }
174
175 struct sync_ctx {
176   /* This flag is set by the callbacks, so we know we've done
177    * the callbacks as expected, and in the right sequence.
178    * 0 = not called, 1 = reply_cb called.
179    */
180   int cb_sequence;
181   struct guestfs_message_header hdr;
182   struct guestfs_message_error err;
183 };
184
185 static void sync_reply_cb (guestfs_h *g, void *data, XDR *xdr)
186 {
187   guestfs_main_loop *ml = guestfs_get_main_loop (g);
188   struct sync_ctx *ctx = (struct sync_ctx *) data;
189
190   /* This should definitely not happen. */
191   if (ctx->cb_sequence != 0) {
192     ctx->cb_sequence = 9999;
193     error (g, "%s: internal error: reply callback called twice", "guestfs_sync");
194     return;
195   }
196
197   ml->main_loop_quit (ml, g);
198
199   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
200     error (g, "%s: failed to parse reply header", "guestfs_sync");
201     return;
202   }
203   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
204     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
205       error (g, "%s: failed to parse reply error", "guestfs_sync");
206       return;
207     }
208     goto done;
209   }
210  done:
211   ctx->cb_sequence = 1;
212 }
213
214 int guestfs_sync (guestfs_h *g)
215 {
216   struct sync_ctx ctx;
217   guestfs_main_loop *ml = guestfs_get_main_loop (g);
218   int serial;
219
220   if (check_state (g, "guestfs_sync") == -1) return -1;
221   guestfs_set_busy (g);
222
223   memset (&ctx, 0, sizeof ctx);
224
225   serial = guestfs__send_sync (g, GUESTFS_PROC_SYNC, NULL, NULL);
226   if (serial == -1) {
227     guestfs_end_busy (g);
228     return -1;
229   }
230
231   guestfs__switch_to_receiving (g);
232   ctx.cb_sequence = 0;
233   guestfs_set_reply_callback (g, sync_reply_cb, &ctx);
234   (void) ml->main_loop_run (ml, g);
235   guestfs_set_reply_callback (g, NULL, NULL);
236   if (ctx.cb_sequence != 1) {
237     error (g, "%s reply failed, see earlier error messages", "guestfs_sync");
238     guestfs_end_busy (g);
239     return -1;
240   }
241
242   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SYNC, serial) == -1) {
243     guestfs_end_busy (g);
244     return -1;
245   }
246
247   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
248     error (g, "%s", ctx.err.error_message);
249     free (ctx.err.error_message);
250     guestfs_end_busy (g);
251     return -1;
252   }
253
254   guestfs_end_busy (g);
255   return 0;
256 }
257
258 struct touch_ctx {
259   /* This flag is set by the callbacks, so we know we've done
260    * the callbacks as expected, and in the right sequence.
261    * 0 = not called, 1 = reply_cb called.
262    */
263   int cb_sequence;
264   struct guestfs_message_header hdr;
265   struct guestfs_message_error err;
266 };
267
268 static void touch_reply_cb (guestfs_h *g, void *data, XDR *xdr)
269 {
270   guestfs_main_loop *ml = guestfs_get_main_loop (g);
271   struct touch_ctx *ctx = (struct touch_ctx *) data;
272
273   /* This should definitely not happen. */
274   if (ctx->cb_sequence != 0) {
275     ctx->cb_sequence = 9999;
276     error (g, "%s: internal error: reply callback called twice", "guestfs_touch");
277     return;
278   }
279
280   ml->main_loop_quit (ml, g);
281
282   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
283     error (g, "%s: failed to parse reply header", "guestfs_touch");
284     return;
285   }
286   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
287     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
288       error (g, "%s: failed to parse reply error", "guestfs_touch");
289       return;
290     }
291     goto done;
292   }
293  done:
294   ctx->cb_sequence = 1;
295 }
296
297 int guestfs_touch (guestfs_h *g,
298                 const char *path)
299 {
300   struct guestfs_touch_args args;
301   struct touch_ctx ctx;
302   guestfs_main_loop *ml = guestfs_get_main_loop (g);
303   int serial;
304
305   if (check_state (g, "guestfs_touch") == -1) return -1;
306   guestfs_set_busy (g);
307
308   memset (&ctx, 0, sizeof ctx);
309
310   args.path = (char *) path;
311   serial = guestfs__send_sync (g, GUESTFS_PROC_TOUCH,
312         (xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
313   if (serial == -1) {
314     guestfs_end_busy (g);
315     return -1;
316   }
317
318   guestfs__switch_to_receiving (g);
319   ctx.cb_sequence = 0;
320   guestfs_set_reply_callback (g, touch_reply_cb, &ctx);
321   (void) ml->main_loop_run (ml, g);
322   guestfs_set_reply_callback (g, NULL, NULL);
323   if (ctx.cb_sequence != 1) {
324     error (g, "%s reply failed, see earlier error messages", "guestfs_touch");
325     guestfs_end_busy (g);
326     return -1;
327   }
328
329   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TOUCH, serial) == -1) {
330     guestfs_end_busy (g);
331     return -1;
332   }
333
334   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
335     error (g, "%s", ctx.err.error_message);
336     free (ctx.err.error_message);
337     guestfs_end_busy (g);
338     return -1;
339   }
340
341   guestfs_end_busy (g);
342   return 0;
343 }
344
345 struct cat_ctx {
346   /* This flag is set by the callbacks, so we know we've done
347    * the callbacks as expected, and in the right sequence.
348    * 0 = not called, 1 = reply_cb called.
349    */
350   int cb_sequence;
351   struct guestfs_message_header hdr;
352   struct guestfs_message_error err;
353   struct guestfs_cat_ret ret;
354 };
355
356 static void cat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
357 {
358   guestfs_main_loop *ml = guestfs_get_main_loop (g);
359   struct cat_ctx *ctx = (struct cat_ctx *) data;
360
361   /* This should definitely not happen. */
362   if (ctx->cb_sequence != 0) {
363     ctx->cb_sequence = 9999;
364     error (g, "%s: internal error: reply callback called twice", "guestfs_cat");
365     return;
366   }
367
368   ml->main_loop_quit (ml, g);
369
370   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
371     error (g, "%s: failed to parse reply header", "guestfs_cat");
372     return;
373   }
374   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
375     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
376       error (g, "%s: failed to parse reply error", "guestfs_cat");
377       return;
378     }
379     goto done;
380   }
381   if (!xdr_guestfs_cat_ret (xdr, &ctx->ret)) {
382     error (g, "%s: failed to parse reply", "guestfs_cat");
383     return;
384   }
385  done:
386   ctx->cb_sequence = 1;
387 }
388
389 char *guestfs_cat (guestfs_h *g,
390                 const char *path)
391 {
392   struct guestfs_cat_args args;
393   struct cat_ctx ctx;
394   guestfs_main_loop *ml = guestfs_get_main_loop (g);
395   int serial;
396
397   if (check_state (g, "guestfs_cat") == -1) return NULL;
398   guestfs_set_busy (g);
399
400   memset (&ctx, 0, sizeof ctx);
401
402   args.path = (char *) path;
403   serial = guestfs__send_sync (g, GUESTFS_PROC_CAT,
404         (xdrproc_t) xdr_guestfs_cat_args, (char *) &args);
405   if (serial == -1) {
406     guestfs_end_busy (g);
407     return NULL;
408   }
409
410   guestfs__switch_to_receiving (g);
411   ctx.cb_sequence = 0;
412   guestfs_set_reply_callback (g, cat_reply_cb, &ctx);
413   (void) ml->main_loop_run (ml, g);
414   guestfs_set_reply_callback (g, NULL, NULL);
415   if (ctx.cb_sequence != 1) {
416     error (g, "%s reply failed, see earlier error messages", "guestfs_cat");
417     guestfs_end_busy (g);
418     return NULL;
419   }
420
421   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CAT, serial) == -1) {
422     guestfs_end_busy (g);
423     return NULL;
424   }
425
426   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
427     error (g, "%s", ctx.err.error_message);
428     free (ctx.err.error_message);
429     guestfs_end_busy (g);
430     return NULL;
431   }
432
433   guestfs_end_busy (g);
434   return ctx.ret.content; /* caller will free */
435 }
436
437 struct ll_ctx {
438   /* This flag is set by the callbacks, so we know we've done
439    * the callbacks as expected, and in the right sequence.
440    * 0 = not called, 1 = reply_cb called.
441    */
442   int cb_sequence;
443   struct guestfs_message_header hdr;
444   struct guestfs_message_error err;
445   struct guestfs_ll_ret ret;
446 };
447
448 static void ll_reply_cb (guestfs_h *g, void *data, XDR *xdr)
449 {
450   guestfs_main_loop *ml = guestfs_get_main_loop (g);
451   struct ll_ctx *ctx = (struct ll_ctx *) data;
452
453   /* This should definitely not happen. */
454   if (ctx->cb_sequence != 0) {
455     ctx->cb_sequence = 9999;
456     error (g, "%s: internal error: reply callback called twice", "guestfs_ll");
457     return;
458   }
459
460   ml->main_loop_quit (ml, g);
461
462   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
463     error (g, "%s: failed to parse reply header", "guestfs_ll");
464     return;
465   }
466   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
467     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
468       error (g, "%s: failed to parse reply error", "guestfs_ll");
469       return;
470     }
471     goto done;
472   }
473   if (!xdr_guestfs_ll_ret (xdr, &ctx->ret)) {
474     error (g, "%s: failed to parse reply", "guestfs_ll");
475     return;
476   }
477  done:
478   ctx->cb_sequence = 1;
479 }
480
481 char *guestfs_ll (guestfs_h *g,
482                 const char *directory)
483 {
484   struct guestfs_ll_args args;
485   struct ll_ctx ctx;
486   guestfs_main_loop *ml = guestfs_get_main_loop (g);
487   int serial;
488
489   if (check_state (g, "guestfs_ll") == -1) return NULL;
490   guestfs_set_busy (g);
491
492   memset (&ctx, 0, sizeof ctx);
493
494   args.directory = (char *) directory;
495   serial = guestfs__send_sync (g, GUESTFS_PROC_LL,
496         (xdrproc_t) xdr_guestfs_ll_args, (char *) &args);
497   if (serial == -1) {
498     guestfs_end_busy (g);
499     return NULL;
500   }
501
502   guestfs__switch_to_receiving (g);
503   ctx.cb_sequence = 0;
504   guestfs_set_reply_callback (g, ll_reply_cb, &ctx);
505   (void) ml->main_loop_run (ml, g);
506   guestfs_set_reply_callback (g, NULL, NULL);
507   if (ctx.cb_sequence != 1) {
508     error (g, "%s reply failed, see earlier error messages", "guestfs_ll");
509     guestfs_end_busy (g);
510     return NULL;
511   }
512
513   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LL, serial) == -1) {
514     guestfs_end_busy (g);
515     return NULL;
516   }
517
518   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
519     error (g, "%s", ctx.err.error_message);
520     free (ctx.err.error_message);
521     guestfs_end_busy (g);
522     return NULL;
523   }
524
525   guestfs_end_busy (g);
526   return ctx.ret.listing; /* caller will free */
527 }
528
529 struct ls_ctx {
530   /* This flag is set by the callbacks, so we know we've done
531    * the callbacks as expected, and in the right sequence.
532    * 0 = not called, 1 = reply_cb called.
533    */
534   int cb_sequence;
535   struct guestfs_message_header hdr;
536   struct guestfs_message_error err;
537   struct guestfs_ls_ret ret;
538 };
539
540 static void ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
541 {
542   guestfs_main_loop *ml = guestfs_get_main_loop (g);
543   struct ls_ctx *ctx = (struct ls_ctx *) data;
544
545   /* This should definitely not happen. */
546   if (ctx->cb_sequence != 0) {
547     ctx->cb_sequence = 9999;
548     error (g, "%s: internal error: reply callback called twice", "guestfs_ls");
549     return;
550   }
551
552   ml->main_loop_quit (ml, g);
553
554   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
555     error (g, "%s: failed to parse reply header", "guestfs_ls");
556     return;
557   }
558   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
559     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
560       error (g, "%s: failed to parse reply error", "guestfs_ls");
561       return;
562     }
563     goto done;
564   }
565   if (!xdr_guestfs_ls_ret (xdr, &ctx->ret)) {
566     error (g, "%s: failed to parse reply", "guestfs_ls");
567     return;
568   }
569  done:
570   ctx->cb_sequence = 1;
571 }
572
573 char **guestfs_ls (guestfs_h *g,
574                 const char *directory)
575 {
576   struct guestfs_ls_args args;
577   struct ls_ctx ctx;
578   guestfs_main_loop *ml = guestfs_get_main_loop (g);
579   int serial;
580
581   if (check_state (g, "guestfs_ls") == -1) return NULL;
582   guestfs_set_busy (g);
583
584   memset (&ctx, 0, sizeof ctx);
585
586   args.directory = (char *) directory;
587   serial = guestfs__send_sync (g, GUESTFS_PROC_LS,
588         (xdrproc_t) xdr_guestfs_ls_args, (char *) &args);
589   if (serial == -1) {
590     guestfs_end_busy (g);
591     return NULL;
592   }
593
594   guestfs__switch_to_receiving (g);
595   ctx.cb_sequence = 0;
596   guestfs_set_reply_callback (g, ls_reply_cb, &ctx);
597   (void) ml->main_loop_run (ml, g);
598   guestfs_set_reply_callback (g, NULL, NULL);
599   if (ctx.cb_sequence != 1) {
600     error (g, "%s reply failed, see earlier error messages", "guestfs_ls");
601     guestfs_end_busy (g);
602     return NULL;
603   }
604
605   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LS, serial) == -1) {
606     guestfs_end_busy (g);
607     return NULL;
608   }
609
610   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
611     error (g, "%s", ctx.err.error_message);
612     free (ctx.err.error_message);
613     guestfs_end_busy (g);
614     return NULL;
615   }
616
617   guestfs_end_busy (g);
618   /* caller will free this, but we need to add a NULL entry */
619   ctx.ret.listing.listing_val =
620     safe_realloc (g, ctx.ret.listing.listing_val,
621                   sizeof (char *) * (ctx.ret.listing.listing_len + 1));
622   ctx.ret.listing.listing_val[ctx.ret.listing.listing_len] = NULL;
623   return ctx.ret.listing.listing_val;
624 }
625
626 struct list_devices_ctx {
627   /* This flag is set by the callbacks, so we know we've done
628    * the callbacks as expected, and in the right sequence.
629    * 0 = not called, 1 = reply_cb called.
630    */
631   int cb_sequence;
632   struct guestfs_message_header hdr;
633   struct guestfs_message_error err;
634   struct guestfs_list_devices_ret ret;
635 };
636
637 static void list_devices_reply_cb (guestfs_h *g, void *data, XDR *xdr)
638 {
639   guestfs_main_loop *ml = guestfs_get_main_loop (g);
640   struct list_devices_ctx *ctx = (struct list_devices_ctx *) data;
641
642   /* This should definitely not happen. */
643   if (ctx->cb_sequence != 0) {
644     ctx->cb_sequence = 9999;
645     error (g, "%s: internal error: reply callback called twice", "guestfs_list_devices");
646     return;
647   }
648
649   ml->main_loop_quit (ml, g);
650
651   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
652     error (g, "%s: failed to parse reply header", "guestfs_list_devices");
653     return;
654   }
655   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
656     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
657       error (g, "%s: failed to parse reply error", "guestfs_list_devices");
658       return;
659     }
660     goto done;
661   }
662   if (!xdr_guestfs_list_devices_ret (xdr, &ctx->ret)) {
663     error (g, "%s: failed to parse reply", "guestfs_list_devices");
664     return;
665   }
666  done:
667   ctx->cb_sequence = 1;
668 }
669
670 char **guestfs_list_devices (guestfs_h *g)
671 {
672   struct list_devices_ctx ctx;
673   guestfs_main_loop *ml = guestfs_get_main_loop (g);
674   int serial;
675
676   if (check_state (g, "guestfs_list_devices") == -1) return NULL;
677   guestfs_set_busy (g);
678
679   memset (&ctx, 0, sizeof ctx);
680
681   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
682   if (serial == -1) {
683     guestfs_end_busy (g);
684     return NULL;
685   }
686
687   guestfs__switch_to_receiving (g);
688   ctx.cb_sequence = 0;
689   guestfs_set_reply_callback (g, list_devices_reply_cb, &ctx);
690   (void) ml->main_loop_run (ml, g);
691   guestfs_set_reply_callback (g, NULL, NULL);
692   if (ctx.cb_sequence != 1) {
693     error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices");
694     guestfs_end_busy (g);
695     return NULL;
696   }
697
698   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1) {
699     guestfs_end_busy (g);
700     return NULL;
701   }
702
703   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
704     error (g, "%s", ctx.err.error_message);
705     free (ctx.err.error_message);
706     guestfs_end_busy (g);
707     return NULL;
708   }
709
710   guestfs_end_busy (g);
711   /* caller will free this, but we need to add a NULL entry */
712   ctx.ret.devices.devices_val =
713     safe_realloc (g, ctx.ret.devices.devices_val,
714                   sizeof (char *) * (ctx.ret.devices.devices_len + 1));
715   ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL;
716   return ctx.ret.devices.devices_val;
717 }
718
719 struct list_partitions_ctx {
720   /* This flag is set by the callbacks, so we know we've done
721    * the callbacks as expected, and in the right sequence.
722    * 0 = not called, 1 = reply_cb called.
723    */
724   int cb_sequence;
725   struct guestfs_message_header hdr;
726   struct guestfs_message_error err;
727   struct guestfs_list_partitions_ret ret;
728 };
729
730 static void list_partitions_reply_cb (guestfs_h *g, void *data, XDR *xdr)
731 {
732   guestfs_main_loop *ml = guestfs_get_main_loop (g);
733   struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data;
734
735   /* This should definitely not happen. */
736   if (ctx->cb_sequence != 0) {
737     ctx->cb_sequence = 9999;
738     error (g, "%s: internal error: reply callback called twice", "guestfs_list_partitions");
739     return;
740   }
741
742   ml->main_loop_quit (ml, g);
743
744   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
745     error (g, "%s: failed to parse reply header", "guestfs_list_partitions");
746     return;
747   }
748   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
749     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
750       error (g, "%s: failed to parse reply error", "guestfs_list_partitions");
751       return;
752     }
753     goto done;
754   }
755   if (!xdr_guestfs_list_partitions_ret (xdr, &ctx->ret)) {
756     error (g, "%s: failed to parse reply", "guestfs_list_partitions");
757     return;
758   }
759  done:
760   ctx->cb_sequence = 1;
761 }
762
763 char **guestfs_list_partitions (guestfs_h *g)
764 {
765   struct list_partitions_ctx ctx;
766   guestfs_main_loop *ml = guestfs_get_main_loop (g);
767   int serial;
768
769   if (check_state (g, "guestfs_list_partitions") == -1) return NULL;
770   guestfs_set_busy (g);
771
772   memset (&ctx, 0, sizeof ctx);
773
774   serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
775   if (serial == -1) {
776     guestfs_end_busy (g);
777     return NULL;
778   }
779
780   guestfs__switch_to_receiving (g);
781   ctx.cb_sequence = 0;
782   guestfs_set_reply_callback (g, list_partitions_reply_cb, &ctx);
783   (void) ml->main_loop_run (ml, g);
784   guestfs_set_reply_callback (g, NULL, NULL);
785   if (ctx.cb_sequence != 1) {
786     error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions");
787     guestfs_end_busy (g);
788     return NULL;
789   }
790
791   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1) {
792     guestfs_end_busy (g);
793     return NULL;
794   }
795
796   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
797     error (g, "%s", ctx.err.error_message);
798     free (ctx.err.error_message);
799     guestfs_end_busy (g);
800     return NULL;
801   }
802
803   guestfs_end_busy (g);
804   /* caller will free this, but we need to add a NULL entry */
805   ctx.ret.partitions.partitions_val =
806     safe_realloc (g, ctx.ret.partitions.partitions_val,
807                   sizeof (char *) * (ctx.ret.partitions.partitions_len + 1));
808   ctx.ret.partitions.partitions_val[ctx.ret.partitions.partitions_len] = NULL;
809   return ctx.ret.partitions.partitions_val;
810 }
811
812 struct pvs_ctx {
813   /* This flag is set by the callbacks, so we know we've done
814    * the callbacks as expected, and in the right sequence.
815    * 0 = not called, 1 = reply_cb called.
816    */
817   int cb_sequence;
818   struct guestfs_message_header hdr;
819   struct guestfs_message_error err;
820   struct guestfs_pvs_ret ret;
821 };
822
823 static void pvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
824 {
825   guestfs_main_loop *ml = guestfs_get_main_loop (g);
826   struct pvs_ctx *ctx = (struct pvs_ctx *) data;
827
828   /* This should definitely not happen. */
829   if (ctx->cb_sequence != 0) {
830     ctx->cb_sequence = 9999;
831     error (g, "%s: internal error: reply callback called twice", "guestfs_pvs");
832     return;
833   }
834
835   ml->main_loop_quit (ml, g);
836
837   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
838     error (g, "%s: failed to parse reply header", "guestfs_pvs");
839     return;
840   }
841   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
842     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
843       error (g, "%s: failed to parse reply error", "guestfs_pvs");
844       return;
845     }
846     goto done;
847   }
848   if (!xdr_guestfs_pvs_ret (xdr, &ctx->ret)) {
849     error (g, "%s: failed to parse reply", "guestfs_pvs");
850     return;
851   }
852  done:
853   ctx->cb_sequence = 1;
854 }
855
856 char **guestfs_pvs (guestfs_h *g)
857 {
858   struct pvs_ctx ctx;
859   guestfs_main_loop *ml = guestfs_get_main_loop (g);
860   int serial;
861
862   if (check_state (g, "guestfs_pvs") == -1) return NULL;
863   guestfs_set_busy (g);
864
865   memset (&ctx, 0, sizeof ctx);
866
867   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS, NULL, NULL);
868   if (serial == -1) {
869     guestfs_end_busy (g);
870     return NULL;
871   }
872
873   guestfs__switch_to_receiving (g);
874   ctx.cb_sequence = 0;
875   guestfs_set_reply_callback (g, pvs_reply_cb, &ctx);
876   (void) ml->main_loop_run (ml, g);
877   guestfs_set_reply_callback (g, NULL, NULL);
878   if (ctx.cb_sequence != 1) {
879     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs");
880     guestfs_end_busy (g);
881     return NULL;
882   }
883
884   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS, serial) == -1) {
885     guestfs_end_busy (g);
886     return NULL;
887   }
888
889   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
890     error (g, "%s", ctx.err.error_message);
891     free (ctx.err.error_message);
892     guestfs_end_busy (g);
893     return NULL;
894   }
895
896   guestfs_end_busy (g);
897   /* caller will free this, but we need to add a NULL entry */
898   ctx.ret.physvols.physvols_val =
899     safe_realloc (g, ctx.ret.physvols.physvols_val,
900                   sizeof (char *) * (ctx.ret.physvols.physvols_len + 1));
901   ctx.ret.physvols.physvols_val[ctx.ret.physvols.physvols_len] = NULL;
902   return ctx.ret.physvols.physvols_val;
903 }
904
905 struct vgs_ctx {
906   /* This flag is set by the callbacks, so we know we've done
907    * the callbacks as expected, and in the right sequence.
908    * 0 = not called, 1 = reply_cb called.
909    */
910   int cb_sequence;
911   struct guestfs_message_header hdr;
912   struct guestfs_message_error err;
913   struct guestfs_vgs_ret ret;
914 };
915
916 static void vgs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
917 {
918   guestfs_main_loop *ml = guestfs_get_main_loop (g);
919   struct vgs_ctx *ctx = (struct vgs_ctx *) data;
920
921   /* This should definitely not happen. */
922   if (ctx->cb_sequence != 0) {
923     ctx->cb_sequence = 9999;
924     error (g, "%s: internal error: reply callback called twice", "guestfs_vgs");
925     return;
926   }
927
928   ml->main_loop_quit (ml, g);
929
930   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
931     error (g, "%s: failed to parse reply header", "guestfs_vgs");
932     return;
933   }
934   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
935     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
936       error (g, "%s: failed to parse reply error", "guestfs_vgs");
937       return;
938     }
939     goto done;
940   }
941   if (!xdr_guestfs_vgs_ret (xdr, &ctx->ret)) {
942     error (g, "%s: failed to parse reply", "guestfs_vgs");
943     return;
944   }
945  done:
946   ctx->cb_sequence = 1;
947 }
948
949 char **guestfs_vgs (guestfs_h *g)
950 {
951   struct vgs_ctx ctx;
952   guestfs_main_loop *ml = guestfs_get_main_loop (g);
953   int serial;
954
955   if (check_state (g, "guestfs_vgs") == -1) return NULL;
956   guestfs_set_busy (g);
957
958   memset (&ctx, 0, sizeof ctx);
959
960   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS, NULL, NULL);
961   if (serial == -1) {
962     guestfs_end_busy (g);
963     return NULL;
964   }
965
966   guestfs__switch_to_receiving (g);
967   ctx.cb_sequence = 0;
968   guestfs_set_reply_callback (g, vgs_reply_cb, &ctx);
969   (void) ml->main_loop_run (ml, g);
970   guestfs_set_reply_callback (g, NULL, NULL);
971   if (ctx.cb_sequence != 1) {
972     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs");
973     guestfs_end_busy (g);
974     return NULL;
975   }
976
977   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS, serial) == -1) {
978     guestfs_end_busy (g);
979     return NULL;
980   }
981
982   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
983     error (g, "%s", ctx.err.error_message);
984     free (ctx.err.error_message);
985     guestfs_end_busy (g);
986     return NULL;
987   }
988
989   guestfs_end_busy (g);
990   /* caller will free this, but we need to add a NULL entry */
991   ctx.ret.volgroups.volgroups_val =
992     safe_realloc (g, ctx.ret.volgroups.volgroups_val,
993                   sizeof (char *) * (ctx.ret.volgroups.volgroups_len + 1));
994   ctx.ret.volgroups.volgroups_val[ctx.ret.volgroups.volgroups_len] = NULL;
995   return ctx.ret.volgroups.volgroups_val;
996 }
997
998 struct lvs_ctx {
999   /* This flag is set by the callbacks, so we know we've done
1000    * the callbacks as expected, and in the right sequence.
1001    * 0 = not called, 1 = reply_cb called.
1002    */
1003   int cb_sequence;
1004   struct guestfs_message_header hdr;
1005   struct guestfs_message_error err;
1006   struct guestfs_lvs_ret ret;
1007 };
1008
1009 static void lvs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1010 {
1011   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1012   struct lvs_ctx *ctx = (struct lvs_ctx *) data;
1013
1014   /* This should definitely not happen. */
1015   if (ctx->cb_sequence != 0) {
1016     ctx->cb_sequence = 9999;
1017     error (g, "%s: internal error: reply callback called twice", "guestfs_lvs");
1018     return;
1019   }
1020
1021   ml->main_loop_quit (ml, g);
1022
1023   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1024     error (g, "%s: failed to parse reply header", "guestfs_lvs");
1025     return;
1026   }
1027   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1028     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1029       error (g, "%s: failed to parse reply error", "guestfs_lvs");
1030       return;
1031     }
1032     goto done;
1033   }
1034   if (!xdr_guestfs_lvs_ret (xdr, &ctx->ret)) {
1035     error (g, "%s: failed to parse reply", "guestfs_lvs");
1036     return;
1037   }
1038  done:
1039   ctx->cb_sequence = 1;
1040 }
1041
1042 char **guestfs_lvs (guestfs_h *g)
1043 {
1044   struct lvs_ctx ctx;
1045   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1046   int serial;
1047
1048   if (check_state (g, "guestfs_lvs") == -1) return NULL;
1049   guestfs_set_busy (g);
1050
1051   memset (&ctx, 0, sizeof ctx);
1052
1053   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS, NULL, NULL);
1054   if (serial == -1) {
1055     guestfs_end_busy (g);
1056     return NULL;
1057   }
1058
1059   guestfs__switch_to_receiving (g);
1060   ctx.cb_sequence = 0;
1061   guestfs_set_reply_callback (g, lvs_reply_cb, &ctx);
1062   (void) ml->main_loop_run (ml, g);
1063   guestfs_set_reply_callback (g, NULL, NULL);
1064   if (ctx.cb_sequence != 1) {
1065     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs");
1066     guestfs_end_busy (g);
1067     return NULL;
1068   }
1069
1070   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS, serial) == -1) {
1071     guestfs_end_busy (g);
1072     return NULL;
1073   }
1074
1075   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1076     error (g, "%s", ctx.err.error_message);
1077     free (ctx.err.error_message);
1078     guestfs_end_busy (g);
1079     return NULL;
1080   }
1081
1082   guestfs_end_busy (g);
1083   /* caller will free this, but we need to add a NULL entry */
1084   ctx.ret.logvols.logvols_val =
1085     safe_realloc (g, ctx.ret.logvols.logvols_val,
1086                   sizeof (char *) * (ctx.ret.logvols.logvols_len + 1));
1087   ctx.ret.logvols.logvols_val[ctx.ret.logvols.logvols_len] = NULL;
1088   return ctx.ret.logvols.logvols_val;
1089 }
1090
1091 struct pvs_full_ctx {
1092   /* This flag is set by the callbacks, so we know we've done
1093    * the callbacks as expected, and in the right sequence.
1094    * 0 = not called, 1 = reply_cb called.
1095    */
1096   int cb_sequence;
1097   struct guestfs_message_header hdr;
1098   struct guestfs_message_error err;
1099   struct guestfs_pvs_full_ret ret;
1100 };
1101
1102 static void pvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1103 {
1104   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1105   struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data;
1106
1107   /* This should definitely not happen. */
1108   if (ctx->cb_sequence != 0) {
1109     ctx->cb_sequence = 9999;
1110     error (g, "%s: internal error: reply callback called twice", "guestfs_pvs_full");
1111     return;
1112   }
1113
1114   ml->main_loop_quit (ml, g);
1115
1116   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1117     error (g, "%s: failed to parse reply header", "guestfs_pvs_full");
1118     return;
1119   }
1120   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1121     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1122       error (g, "%s: failed to parse reply error", "guestfs_pvs_full");
1123       return;
1124     }
1125     goto done;
1126   }
1127   if (!xdr_guestfs_pvs_full_ret (xdr, &ctx->ret)) {
1128     error (g, "%s: failed to parse reply", "guestfs_pvs_full");
1129     return;
1130   }
1131  done:
1132   ctx->cb_sequence = 1;
1133 }
1134
1135 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
1136 {
1137   struct pvs_full_ctx ctx;
1138   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1139   int serial;
1140
1141   if (check_state (g, "guestfs_pvs_full") == -1) return NULL;
1142   guestfs_set_busy (g);
1143
1144   memset (&ctx, 0, sizeof ctx);
1145
1146   serial = guestfs__send_sync (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
1147   if (serial == -1) {
1148     guestfs_end_busy (g);
1149     return NULL;
1150   }
1151
1152   guestfs__switch_to_receiving (g);
1153   ctx.cb_sequence = 0;
1154   guestfs_set_reply_callback (g, pvs_full_reply_cb, &ctx);
1155   (void) ml->main_loop_run (ml, g);
1156   guestfs_set_reply_callback (g, NULL, NULL);
1157   if (ctx.cb_sequence != 1) {
1158     error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full");
1159     guestfs_end_busy (g);
1160     return NULL;
1161   }
1162
1163   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1) {
1164     guestfs_end_busy (g);
1165     return NULL;
1166   }
1167
1168   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1169     error (g, "%s", ctx.err.error_message);
1170     free (ctx.err.error_message);
1171     guestfs_end_busy (g);
1172     return NULL;
1173   }
1174
1175   guestfs_end_busy (g);
1176   /* caller will free this */
1177   return safe_memdup (g, &ctx.ret.physvols, sizeof (ctx.ret.physvols));
1178 }
1179
1180 struct vgs_full_ctx {
1181   /* This flag is set by the callbacks, so we know we've done
1182    * the callbacks as expected, and in the right sequence.
1183    * 0 = not called, 1 = reply_cb called.
1184    */
1185   int cb_sequence;
1186   struct guestfs_message_header hdr;
1187   struct guestfs_message_error err;
1188   struct guestfs_vgs_full_ret ret;
1189 };
1190
1191 static void vgs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1192 {
1193   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1194   struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data;
1195
1196   /* This should definitely not happen. */
1197   if (ctx->cb_sequence != 0) {
1198     ctx->cb_sequence = 9999;
1199     error (g, "%s: internal error: reply callback called twice", "guestfs_vgs_full");
1200     return;
1201   }
1202
1203   ml->main_loop_quit (ml, g);
1204
1205   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1206     error (g, "%s: failed to parse reply header", "guestfs_vgs_full");
1207     return;
1208   }
1209   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1210     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1211       error (g, "%s: failed to parse reply error", "guestfs_vgs_full");
1212       return;
1213     }
1214     goto done;
1215   }
1216   if (!xdr_guestfs_vgs_full_ret (xdr, &ctx->ret)) {
1217     error (g, "%s: failed to parse reply", "guestfs_vgs_full");
1218     return;
1219   }
1220  done:
1221   ctx->cb_sequence = 1;
1222 }
1223
1224 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
1225 {
1226   struct vgs_full_ctx ctx;
1227   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1228   int serial;
1229
1230   if (check_state (g, "guestfs_vgs_full") == -1) return NULL;
1231   guestfs_set_busy (g);
1232
1233   memset (&ctx, 0, sizeof ctx);
1234
1235   serial = guestfs__send_sync (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
1236   if (serial == -1) {
1237     guestfs_end_busy (g);
1238     return NULL;
1239   }
1240
1241   guestfs__switch_to_receiving (g);
1242   ctx.cb_sequence = 0;
1243   guestfs_set_reply_callback (g, vgs_full_reply_cb, &ctx);
1244   (void) ml->main_loop_run (ml, g);
1245   guestfs_set_reply_callback (g, NULL, NULL);
1246   if (ctx.cb_sequence != 1) {
1247     error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full");
1248     guestfs_end_busy (g);
1249     return NULL;
1250   }
1251
1252   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1) {
1253     guestfs_end_busy (g);
1254     return NULL;
1255   }
1256
1257   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1258     error (g, "%s", ctx.err.error_message);
1259     free (ctx.err.error_message);
1260     guestfs_end_busy (g);
1261     return NULL;
1262   }
1263
1264   guestfs_end_busy (g);
1265   /* caller will free this */
1266   return safe_memdup (g, &ctx.ret.volgroups, sizeof (ctx.ret.volgroups));
1267 }
1268
1269 struct lvs_full_ctx {
1270   /* This flag is set by the callbacks, so we know we've done
1271    * the callbacks as expected, and in the right sequence.
1272    * 0 = not called, 1 = reply_cb called.
1273    */
1274   int cb_sequence;
1275   struct guestfs_message_header hdr;
1276   struct guestfs_message_error err;
1277   struct guestfs_lvs_full_ret ret;
1278 };
1279
1280 static void lvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1281 {
1282   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1283   struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data;
1284
1285   /* This should definitely not happen. */
1286   if (ctx->cb_sequence != 0) {
1287     ctx->cb_sequence = 9999;
1288     error (g, "%s: internal error: reply callback called twice", "guestfs_lvs_full");
1289     return;
1290   }
1291
1292   ml->main_loop_quit (ml, g);
1293
1294   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1295     error (g, "%s: failed to parse reply header", "guestfs_lvs_full");
1296     return;
1297   }
1298   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1299     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1300       error (g, "%s: failed to parse reply error", "guestfs_lvs_full");
1301       return;
1302     }
1303     goto done;
1304   }
1305   if (!xdr_guestfs_lvs_full_ret (xdr, &ctx->ret)) {
1306     error (g, "%s: failed to parse reply", "guestfs_lvs_full");
1307     return;
1308   }
1309  done:
1310   ctx->cb_sequence = 1;
1311 }
1312
1313 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
1314 {
1315   struct lvs_full_ctx ctx;
1316   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1317   int serial;
1318
1319   if (check_state (g, "guestfs_lvs_full") == -1) return NULL;
1320   guestfs_set_busy (g);
1321
1322   memset (&ctx, 0, sizeof ctx);
1323
1324   serial = guestfs__send_sync (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
1325   if (serial == -1) {
1326     guestfs_end_busy (g);
1327     return NULL;
1328   }
1329
1330   guestfs__switch_to_receiving (g);
1331   ctx.cb_sequence = 0;
1332   guestfs_set_reply_callback (g, lvs_full_reply_cb, &ctx);
1333   (void) ml->main_loop_run (ml, g);
1334   guestfs_set_reply_callback (g, NULL, NULL);
1335   if (ctx.cb_sequence != 1) {
1336     error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full");
1337     guestfs_end_busy (g);
1338     return NULL;
1339   }
1340
1341   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1) {
1342     guestfs_end_busy (g);
1343     return NULL;
1344   }
1345
1346   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1347     error (g, "%s", ctx.err.error_message);
1348     free (ctx.err.error_message);
1349     guestfs_end_busy (g);
1350     return NULL;
1351   }
1352
1353   guestfs_end_busy (g);
1354   /* caller will free this */
1355   return safe_memdup (g, &ctx.ret.logvols, sizeof (ctx.ret.logvols));
1356 }
1357
1358 struct read_lines_ctx {
1359   /* This flag is set by the callbacks, so we know we've done
1360    * the callbacks as expected, and in the right sequence.
1361    * 0 = not called, 1 = reply_cb called.
1362    */
1363   int cb_sequence;
1364   struct guestfs_message_header hdr;
1365   struct guestfs_message_error err;
1366   struct guestfs_read_lines_ret ret;
1367 };
1368
1369 static void read_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1370 {
1371   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1372   struct read_lines_ctx *ctx = (struct read_lines_ctx *) data;
1373
1374   /* This should definitely not happen. */
1375   if (ctx->cb_sequence != 0) {
1376     ctx->cb_sequence = 9999;
1377     error (g, "%s: internal error: reply callback called twice", "guestfs_read_lines");
1378     return;
1379   }
1380
1381   ml->main_loop_quit (ml, g);
1382
1383   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1384     error (g, "%s: failed to parse reply header", "guestfs_read_lines");
1385     return;
1386   }
1387   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1388     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1389       error (g, "%s: failed to parse reply error", "guestfs_read_lines");
1390       return;
1391     }
1392     goto done;
1393   }
1394   if (!xdr_guestfs_read_lines_ret (xdr, &ctx->ret)) {
1395     error (g, "%s: failed to parse reply", "guestfs_read_lines");
1396     return;
1397   }
1398  done:
1399   ctx->cb_sequence = 1;
1400 }
1401
1402 char **guestfs_read_lines (guestfs_h *g,
1403                 const char *path)
1404 {
1405   struct guestfs_read_lines_args args;
1406   struct read_lines_ctx ctx;
1407   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1408   int serial;
1409
1410   if (check_state (g, "guestfs_read_lines") == -1) return NULL;
1411   guestfs_set_busy (g);
1412
1413   memset (&ctx, 0, sizeof ctx);
1414
1415   args.path = (char *) path;
1416   serial = guestfs__send_sync (g, GUESTFS_PROC_READ_LINES,
1417         (xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args);
1418   if (serial == -1) {
1419     guestfs_end_busy (g);
1420     return NULL;
1421   }
1422
1423   guestfs__switch_to_receiving (g);
1424   ctx.cb_sequence = 0;
1425   guestfs_set_reply_callback (g, read_lines_reply_cb, &ctx);
1426   (void) ml->main_loop_run (ml, g);
1427   guestfs_set_reply_callback (g, NULL, NULL);
1428   if (ctx.cb_sequence != 1) {
1429     error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines");
1430     guestfs_end_busy (g);
1431     return NULL;
1432   }
1433
1434   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_READ_LINES, serial) == -1) {
1435     guestfs_end_busy (g);
1436     return NULL;
1437   }
1438
1439   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1440     error (g, "%s", ctx.err.error_message);
1441     free (ctx.err.error_message);
1442     guestfs_end_busy (g);
1443     return NULL;
1444   }
1445
1446   guestfs_end_busy (g);
1447   /* caller will free this, but we need to add a NULL entry */
1448   ctx.ret.lines.lines_val =
1449     safe_realloc (g, ctx.ret.lines.lines_val,
1450                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
1451   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
1452   return ctx.ret.lines.lines_val;
1453 }
1454
1455 struct aug_init_ctx {
1456   /* This flag is set by the callbacks, so we know we've done
1457    * the callbacks as expected, and in the right sequence.
1458    * 0 = not called, 1 = reply_cb called.
1459    */
1460   int cb_sequence;
1461   struct guestfs_message_header hdr;
1462   struct guestfs_message_error err;
1463 };
1464
1465 static void aug_init_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1466 {
1467   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1468   struct aug_init_ctx *ctx = (struct aug_init_ctx *) data;
1469
1470   /* This should definitely not happen. */
1471   if (ctx->cb_sequence != 0) {
1472     ctx->cb_sequence = 9999;
1473     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_init");
1474     return;
1475   }
1476
1477   ml->main_loop_quit (ml, g);
1478
1479   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1480     error (g, "%s: failed to parse reply header", "guestfs_aug_init");
1481     return;
1482   }
1483   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1484     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1485       error (g, "%s: failed to parse reply error", "guestfs_aug_init");
1486       return;
1487     }
1488     goto done;
1489   }
1490  done:
1491   ctx->cb_sequence = 1;
1492 }
1493
1494 int guestfs_aug_init (guestfs_h *g,
1495                 const char *root,
1496                 int flags)
1497 {
1498   struct guestfs_aug_init_args args;
1499   struct aug_init_ctx ctx;
1500   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1501   int serial;
1502
1503   if (check_state (g, "guestfs_aug_init") == -1) return -1;
1504   guestfs_set_busy (g);
1505
1506   memset (&ctx, 0, sizeof ctx);
1507
1508   args.root = (char *) root;
1509   args.flags = flags;
1510   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INIT,
1511         (xdrproc_t) xdr_guestfs_aug_init_args, (char *) &args);
1512   if (serial == -1) {
1513     guestfs_end_busy (g);
1514     return -1;
1515   }
1516
1517   guestfs__switch_to_receiving (g);
1518   ctx.cb_sequence = 0;
1519   guestfs_set_reply_callback (g, aug_init_reply_cb, &ctx);
1520   (void) ml->main_loop_run (ml, g);
1521   guestfs_set_reply_callback (g, NULL, NULL);
1522   if (ctx.cb_sequence != 1) {
1523     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init");
1524     guestfs_end_busy (g);
1525     return -1;
1526   }
1527
1528   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1) {
1529     guestfs_end_busy (g);
1530     return -1;
1531   }
1532
1533   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1534     error (g, "%s", ctx.err.error_message);
1535     free (ctx.err.error_message);
1536     guestfs_end_busy (g);
1537     return -1;
1538   }
1539
1540   guestfs_end_busy (g);
1541   return 0;
1542 }
1543
1544 struct aug_close_ctx {
1545   /* This flag is set by the callbacks, so we know we've done
1546    * the callbacks as expected, and in the right sequence.
1547    * 0 = not called, 1 = reply_cb called.
1548    */
1549   int cb_sequence;
1550   struct guestfs_message_header hdr;
1551   struct guestfs_message_error err;
1552 };
1553
1554 static void aug_close_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1555 {
1556   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1557   struct aug_close_ctx *ctx = (struct aug_close_ctx *) data;
1558
1559   /* This should definitely not happen. */
1560   if (ctx->cb_sequence != 0) {
1561     ctx->cb_sequence = 9999;
1562     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_close");
1563     return;
1564   }
1565
1566   ml->main_loop_quit (ml, g);
1567
1568   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1569     error (g, "%s: failed to parse reply header", "guestfs_aug_close");
1570     return;
1571   }
1572   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1573     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1574       error (g, "%s: failed to parse reply error", "guestfs_aug_close");
1575       return;
1576     }
1577     goto done;
1578   }
1579  done:
1580   ctx->cb_sequence = 1;
1581 }
1582
1583 int guestfs_aug_close (guestfs_h *g)
1584 {
1585   struct aug_close_ctx ctx;
1586   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1587   int serial;
1588
1589   if (check_state (g, "guestfs_aug_close") == -1) return -1;
1590   guestfs_set_busy (g);
1591
1592   memset (&ctx, 0, sizeof ctx);
1593
1594   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
1595   if (serial == -1) {
1596     guestfs_end_busy (g);
1597     return -1;
1598   }
1599
1600   guestfs__switch_to_receiving (g);
1601   ctx.cb_sequence = 0;
1602   guestfs_set_reply_callback (g, aug_close_reply_cb, &ctx);
1603   (void) ml->main_loop_run (ml, g);
1604   guestfs_set_reply_callback (g, NULL, NULL);
1605   if (ctx.cb_sequence != 1) {
1606     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close");
1607     guestfs_end_busy (g);
1608     return -1;
1609   }
1610
1611   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1) {
1612     guestfs_end_busy (g);
1613     return -1;
1614   }
1615
1616   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1617     error (g, "%s", ctx.err.error_message);
1618     free (ctx.err.error_message);
1619     guestfs_end_busy (g);
1620     return -1;
1621   }
1622
1623   guestfs_end_busy (g);
1624   return 0;
1625 }
1626
1627 struct aug_defvar_ctx {
1628   /* This flag is set by the callbacks, so we know we've done
1629    * the callbacks as expected, and in the right sequence.
1630    * 0 = not called, 1 = reply_cb called.
1631    */
1632   int cb_sequence;
1633   struct guestfs_message_header hdr;
1634   struct guestfs_message_error err;
1635   struct guestfs_aug_defvar_ret ret;
1636 };
1637
1638 static void aug_defvar_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1639 {
1640   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1641   struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data;
1642
1643   /* This should definitely not happen. */
1644   if (ctx->cb_sequence != 0) {
1645     ctx->cb_sequence = 9999;
1646     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defvar");
1647     return;
1648   }
1649
1650   ml->main_loop_quit (ml, g);
1651
1652   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1653     error (g, "%s: failed to parse reply header", "guestfs_aug_defvar");
1654     return;
1655   }
1656   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1657     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1658       error (g, "%s: failed to parse reply error", "guestfs_aug_defvar");
1659       return;
1660     }
1661     goto done;
1662   }
1663   if (!xdr_guestfs_aug_defvar_ret (xdr, &ctx->ret)) {
1664     error (g, "%s: failed to parse reply", "guestfs_aug_defvar");
1665     return;
1666   }
1667  done:
1668   ctx->cb_sequence = 1;
1669 }
1670
1671 int guestfs_aug_defvar (guestfs_h *g,
1672                 const char *name,
1673                 const char *expr)
1674 {
1675   struct guestfs_aug_defvar_args args;
1676   struct aug_defvar_ctx ctx;
1677   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1678   int serial;
1679
1680   if (check_state (g, "guestfs_aug_defvar") == -1) return -1;
1681   guestfs_set_busy (g);
1682
1683   memset (&ctx, 0, sizeof ctx);
1684
1685   args.name = (char *) name;
1686   args.expr = expr ? (char **) &expr : NULL;
1687   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFVAR,
1688         (xdrproc_t) xdr_guestfs_aug_defvar_args, (char *) &args);
1689   if (serial == -1) {
1690     guestfs_end_busy (g);
1691     return -1;
1692   }
1693
1694   guestfs__switch_to_receiving (g);
1695   ctx.cb_sequence = 0;
1696   guestfs_set_reply_callback (g, aug_defvar_reply_cb, &ctx);
1697   (void) ml->main_loop_run (ml, g);
1698   guestfs_set_reply_callback (g, NULL, NULL);
1699   if (ctx.cb_sequence != 1) {
1700     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar");
1701     guestfs_end_busy (g);
1702     return -1;
1703   }
1704
1705   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1) {
1706     guestfs_end_busy (g);
1707     return -1;
1708   }
1709
1710   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1711     error (g, "%s", ctx.err.error_message);
1712     free (ctx.err.error_message);
1713     guestfs_end_busy (g);
1714     return -1;
1715   }
1716
1717   guestfs_end_busy (g);
1718   return ctx.ret.nrnodes;
1719 }
1720
1721 struct aug_defnode_ctx {
1722   /* This flag is set by the callbacks, so we know we've done
1723    * the callbacks as expected, and in the right sequence.
1724    * 0 = not called, 1 = reply_cb called.
1725    */
1726   int cb_sequence;
1727   struct guestfs_message_header hdr;
1728   struct guestfs_message_error err;
1729   struct guestfs_aug_defnode_ret ret;
1730 };
1731
1732 static void aug_defnode_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1733 {
1734   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1735   struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data;
1736
1737   /* This should definitely not happen. */
1738   if (ctx->cb_sequence != 0) {
1739     ctx->cb_sequence = 9999;
1740     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defnode");
1741     return;
1742   }
1743
1744   ml->main_loop_quit (ml, g);
1745
1746   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1747     error (g, "%s: failed to parse reply header", "guestfs_aug_defnode");
1748     return;
1749   }
1750   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1751     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1752       error (g, "%s: failed to parse reply error", "guestfs_aug_defnode");
1753       return;
1754     }
1755     goto done;
1756   }
1757   if (!xdr_guestfs_aug_defnode_ret (xdr, &ctx->ret)) {
1758     error (g, "%s: failed to parse reply", "guestfs_aug_defnode");
1759     return;
1760   }
1761  done:
1762   ctx->cb_sequence = 1;
1763 }
1764
1765 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
1766                 const char *name,
1767                 const char *expr,
1768                 const char *val)
1769 {
1770   struct guestfs_aug_defnode_args args;
1771   struct aug_defnode_ctx ctx;
1772   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1773   int serial;
1774
1775   if (check_state (g, "guestfs_aug_defnode") == -1) return NULL;
1776   guestfs_set_busy (g);
1777
1778   memset (&ctx, 0, sizeof ctx);
1779
1780   args.name = (char *) name;
1781   args.expr = (char *) expr;
1782   args.val = (char *) val;
1783   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFNODE,
1784         (xdrproc_t) xdr_guestfs_aug_defnode_args, (char *) &args);
1785   if (serial == -1) {
1786     guestfs_end_busy (g);
1787     return NULL;
1788   }
1789
1790   guestfs__switch_to_receiving (g);
1791   ctx.cb_sequence = 0;
1792   guestfs_set_reply_callback (g, aug_defnode_reply_cb, &ctx);
1793   (void) ml->main_loop_run (ml, g);
1794   guestfs_set_reply_callback (g, NULL, NULL);
1795   if (ctx.cb_sequence != 1) {
1796     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode");
1797     guestfs_end_busy (g);
1798     return NULL;
1799   }
1800
1801   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1) {
1802     guestfs_end_busy (g);
1803     return NULL;
1804   }
1805
1806   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1807     error (g, "%s", ctx.err.error_message);
1808     free (ctx.err.error_message);
1809     guestfs_end_busy (g);
1810     return NULL;
1811   }
1812
1813   guestfs_end_busy (g);
1814   /* caller with free this */
1815   return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));
1816 }
1817
1818 struct aug_get_ctx {
1819   /* This flag is set by the callbacks, so we know we've done
1820    * the callbacks as expected, and in the right sequence.
1821    * 0 = not called, 1 = reply_cb called.
1822    */
1823   int cb_sequence;
1824   struct guestfs_message_header hdr;
1825   struct guestfs_message_error err;
1826   struct guestfs_aug_get_ret ret;
1827 };
1828
1829 static void aug_get_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1830 {
1831   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1832   struct aug_get_ctx *ctx = (struct aug_get_ctx *) data;
1833
1834   /* This should definitely not happen. */
1835   if (ctx->cb_sequence != 0) {
1836     ctx->cb_sequence = 9999;
1837     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_get");
1838     return;
1839   }
1840
1841   ml->main_loop_quit (ml, g);
1842
1843   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1844     error (g, "%s: failed to parse reply header", "guestfs_aug_get");
1845     return;
1846   }
1847   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1848     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1849       error (g, "%s: failed to parse reply error", "guestfs_aug_get");
1850       return;
1851     }
1852     goto done;
1853   }
1854   if (!xdr_guestfs_aug_get_ret (xdr, &ctx->ret)) {
1855     error (g, "%s: failed to parse reply", "guestfs_aug_get");
1856     return;
1857   }
1858  done:
1859   ctx->cb_sequence = 1;
1860 }
1861
1862 char *guestfs_aug_get (guestfs_h *g,
1863                 const char *path)
1864 {
1865   struct guestfs_aug_get_args args;
1866   struct aug_get_ctx ctx;
1867   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1868   int serial;
1869
1870   if (check_state (g, "guestfs_aug_get") == -1) return NULL;
1871   guestfs_set_busy (g);
1872
1873   memset (&ctx, 0, sizeof ctx);
1874
1875   args.path = (char *) path;
1876   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_GET,
1877         (xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args);
1878   if (serial == -1) {
1879     guestfs_end_busy (g);
1880     return NULL;
1881   }
1882
1883   guestfs__switch_to_receiving (g);
1884   ctx.cb_sequence = 0;
1885   guestfs_set_reply_callback (g, aug_get_reply_cb, &ctx);
1886   (void) ml->main_loop_run (ml, g);
1887   guestfs_set_reply_callback (g, NULL, NULL);
1888   if (ctx.cb_sequence != 1) {
1889     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get");
1890     guestfs_end_busy (g);
1891     return NULL;
1892   }
1893
1894   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_GET, serial) == -1) {
1895     guestfs_end_busy (g);
1896     return NULL;
1897   }
1898
1899   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1900     error (g, "%s", ctx.err.error_message);
1901     free (ctx.err.error_message);
1902     guestfs_end_busy (g);
1903     return NULL;
1904   }
1905
1906   guestfs_end_busy (g);
1907   return ctx.ret.val; /* caller will free */
1908 }
1909
1910 struct aug_set_ctx {
1911   /* This flag is set by the callbacks, so we know we've done
1912    * the callbacks as expected, and in the right sequence.
1913    * 0 = not called, 1 = reply_cb called.
1914    */
1915   int cb_sequence;
1916   struct guestfs_message_header hdr;
1917   struct guestfs_message_error err;
1918 };
1919
1920 static void aug_set_reply_cb (guestfs_h *g, void *data, XDR *xdr)
1921 {
1922   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1923   struct aug_set_ctx *ctx = (struct aug_set_ctx *) data;
1924
1925   /* This should definitely not happen. */
1926   if (ctx->cb_sequence != 0) {
1927     ctx->cb_sequence = 9999;
1928     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_set");
1929     return;
1930   }
1931
1932   ml->main_loop_quit (ml, g);
1933
1934   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
1935     error (g, "%s: failed to parse reply header", "guestfs_aug_set");
1936     return;
1937   }
1938   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
1939     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
1940       error (g, "%s: failed to parse reply error", "guestfs_aug_set");
1941       return;
1942     }
1943     goto done;
1944   }
1945  done:
1946   ctx->cb_sequence = 1;
1947 }
1948
1949 int guestfs_aug_set (guestfs_h *g,
1950                 const char *path,
1951                 const char *val)
1952 {
1953   struct guestfs_aug_set_args args;
1954   struct aug_set_ctx ctx;
1955   guestfs_main_loop *ml = guestfs_get_main_loop (g);
1956   int serial;
1957
1958   if (check_state (g, "guestfs_aug_set") == -1) return -1;
1959   guestfs_set_busy (g);
1960
1961   memset (&ctx, 0, sizeof ctx);
1962
1963   args.path = (char *) path;
1964   args.val = (char *) val;
1965   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SET,
1966         (xdrproc_t) xdr_guestfs_aug_set_args, (char *) &args);
1967   if (serial == -1) {
1968     guestfs_end_busy (g);
1969     return -1;
1970   }
1971
1972   guestfs__switch_to_receiving (g);
1973   ctx.cb_sequence = 0;
1974   guestfs_set_reply_callback (g, aug_set_reply_cb, &ctx);
1975   (void) ml->main_loop_run (ml, g);
1976   guestfs_set_reply_callback (g, NULL, NULL);
1977   if (ctx.cb_sequence != 1) {
1978     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set");
1979     guestfs_end_busy (g);
1980     return -1;
1981   }
1982
1983   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SET, serial) == -1) {
1984     guestfs_end_busy (g);
1985     return -1;
1986   }
1987
1988   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
1989     error (g, "%s", ctx.err.error_message);
1990     free (ctx.err.error_message);
1991     guestfs_end_busy (g);
1992     return -1;
1993   }
1994
1995   guestfs_end_busy (g);
1996   return 0;
1997 }
1998
1999 struct aug_insert_ctx {
2000   /* This flag is set by the callbacks, so we know we've done
2001    * the callbacks as expected, and in the right sequence.
2002    * 0 = not called, 1 = reply_cb called.
2003    */
2004   int cb_sequence;
2005   struct guestfs_message_header hdr;
2006   struct guestfs_message_error err;
2007 };
2008
2009 static void aug_insert_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2010 {
2011   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2012   struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data;
2013
2014   /* This should definitely not happen. */
2015   if (ctx->cb_sequence != 0) {
2016     ctx->cb_sequence = 9999;
2017     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_insert");
2018     return;
2019   }
2020
2021   ml->main_loop_quit (ml, g);
2022
2023   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2024     error (g, "%s: failed to parse reply header", "guestfs_aug_insert");
2025     return;
2026   }
2027   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2028     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2029       error (g, "%s: failed to parse reply error", "guestfs_aug_insert");
2030       return;
2031     }
2032     goto done;
2033   }
2034  done:
2035   ctx->cb_sequence = 1;
2036 }
2037
2038 int guestfs_aug_insert (guestfs_h *g,
2039                 const char *path,
2040                 const char *label,
2041                 int before)
2042 {
2043   struct guestfs_aug_insert_args args;
2044   struct aug_insert_ctx ctx;
2045   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2046   int serial;
2047
2048   if (check_state (g, "guestfs_aug_insert") == -1) return -1;
2049   guestfs_set_busy (g);
2050
2051   memset (&ctx, 0, sizeof ctx);
2052
2053   args.path = (char *) path;
2054   args.label = (char *) label;
2055   args.before = before;
2056   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INSERT,
2057         (xdrproc_t) xdr_guestfs_aug_insert_args, (char *) &args);
2058   if (serial == -1) {
2059     guestfs_end_busy (g);
2060     return -1;
2061   }
2062
2063   guestfs__switch_to_receiving (g);
2064   ctx.cb_sequence = 0;
2065   guestfs_set_reply_callback (g, aug_insert_reply_cb, &ctx);
2066   (void) ml->main_loop_run (ml, g);
2067   guestfs_set_reply_callback (g, NULL, NULL);
2068   if (ctx.cb_sequence != 1) {
2069     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert");
2070     guestfs_end_busy (g);
2071     return -1;
2072   }
2073
2074   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1) {
2075     guestfs_end_busy (g);
2076     return -1;
2077   }
2078
2079   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2080     error (g, "%s", ctx.err.error_message);
2081     free (ctx.err.error_message);
2082     guestfs_end_busy (g);
2083     return -1;
2084   }
2085
2086   guestfs_end_busy (g);
2087   return 0;
2088 }
2089
2090 struct aug_rm_ctx {
2091   /* This flag is set by the callbacks, so we know we've done
2092    * the callbacks as expected, and in the right sequence.
2093    * 0 = not called, 1 = reply_cb called.
2094    */
2095   int cb_sequence;
2096   struct guestfs_message_header hdr;
2097   struct guestfs_message_error err;
2098   struct guestfs_aug_rm_ret ret;
2099 };
2100
2101 static void aug_rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2102 {
2103   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2104   struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data;
2105
2106   /* This should definitely not happen. */
2107   if (ctx->cb_sequence != 0) {
2108     ctx->cb_sequence = 9999;
2109     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_rm");
2110     return;
2111   }
2112
2113   ml->main_loop_quit (ml, g);
2114
2115   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2116     error (g, "%s: failed to parse reply header", "guestfs_aug_rm");
2117     return;
2118   }
2119   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2120     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2121       error (g, "%s: failed to parse reply error", "guestfs_aug_rm");
2122       return;
2123     }
2124     goto done;
2125   }
2126   if (!xdr_guestfs_aug_rm_ret (xdr, &ctx->ret)) {
2127     error (g, "%s: failed to parse reply", "guestfs_aug_rm");
2128     return;
2129   }
2130  done:
2131   ctx->cb_sequence = 1;
2132 }
2133
2134 int guestfs_aug_rm (guestfs_h *g,
2135                 const char *path)
2136 {
2137   struct guestfs_aug_rm_args args;
2138   struct aug_rm_ctx ctx;
2139   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2140   int serial;
2141
2142   if (check_state (g, "guestfs_aug_rm") == -1) return -1;
2143   guestfs_set_busy (g);
2144
2145   memset (&ctx, 0, sizeof ctx);
2146
2147   args.path = (char *) path;
2148   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_RM,
2149         (xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args);
2150   if (serial == -1) {
2151     guestfs_end_busy (g);
2152     return -1;
2153   }
2154
2155   guestfs__switch_to_receiving (g);
2156   ctx.cb_sequence = 0;
2157   guestfs_set_reply_callback (g, aug_rm_reply_cb, &ctx);
2158   (void) ml->main_loop_run (ml, g);
2159   guestfs_set_reply_callback (g, NULL, NULL);
2160   if (ctx.cb_sequence != 1) {
2161     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm");
2162     guestfs_end_busy (g);
2163     return -1;
2164   }
2165
2166   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_RM, serial) == -1) {
2167     guestfs_end_busy (g);
2168     return -1;
2169   }
2170
2171   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2172     error (g, "%s", ctx.err.error_message);
2173     free (ctx.err.error_message);
2174     guestfs_end_busy (g);
2175     return -1;
2176   }
2177
2178   guestfs_end_busy (g);
2179   return ctx.ret.nrnodes;
2180 }
2181
2182 struct aug_mv_ctx {
2183   /* This flag is set by the callbacks, so we know we've done
2184    * the callbacks as expected, and in the right sequence.
2185    * 0 = not called, 1 = reply_cb called.
2186    */
2187   int cb_sequence;
2188   struct guestfs_message_header hdr;
2189   struct guestfs_message_error err;
2190 };
2191
2192 static void aug_mv_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2193 {
2194   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2195   struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data;
2196
2197   /* This should definitely not happen. */
2198   if (ctx->cb_sequence != 0) {
2199     ctx->cb_sequence = 9999;
2200     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_mv");
2201     return;
2202   }
2203
2204   ml->main_loop_quit (ml, g);
2205
2206   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2207     error (g, "%s: failed to parse reply header", "guestfs_aug_mv");
2208     return;
2209   }
2210   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2211     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2212       error (g, "%s: failed to parse reply error", "guestfs_aug_mv");
2213       return;
2214     }
2215     goto done;
2216   }
2217  done:
2218   ctx->cb_sequence = 1;
2219 }
2220
2221 int guestfs_aug_mv (guestfs_h *g,
2222                 const char *src,
2223                 const char *dest)
2224 {
2225   struct guestfs_aug_mv_args args;
2226   struct aug_mv_ctx ctx;
2227   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2228   int serial;
2229
2230   if (check_state (g, "guestfs_aug_mv") == -1) return -1;
2231   guestfs_set_busy (g);
2232
2233   memset (&ctx, 0, sizeof ctx);
2234
2235   args.src = (char *) src;
2236   args.dest = (char *) dest;
2237   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MV,
2238         (xdrproc_t) xdr_guestfs_aug_mv_args, (char *) &args);
2239   if (serial == -1) {
2240     guestfs_end_busy (g);
2241     return -1;
2242   }
2243
2244   guestfs__switch_to_receiving (g);
2245   ctx.cb_sequence = 0;
2246   guestfs_set_reply_callback (g, aug_mv_reply_cb, &ctx);
2247   (void) ml->main_loop_run (ml, g);
2248   guestfs_set_reply_callback (g, NULL, NULL);
2249   if (ctx.cb_sequence != 1) {
2250     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv");
2251     guestfs_end_busy (g);
2252     return -1;
2253   }
2254
2255   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MV, serial) == -1) {
2256     guestfs_end_busy (g);
2257     return -1;
2258   }
2259
2260   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2261     error (g, "%s", ctx.err.error_message);
2262     free (ctx.err.error_message);
2263     guestfs_end_busy (g);
2264     return -1;
2265   }
2266
2267   guestfs_end_busy (g);
2268   return 0;
2269 }
2270
2271 struct aug_match_ctx {
2272   /* This flag is set by the callbacks, so we know we've done
2273    * the callbacks as expected, and in the right sequence.
2274    * 0 = not called, 1 = reply_cb called.
2275    */
2276   int cb_sequence;
2277   struct guestfs_message_header hdr;
2278   struct guestfs_message_error err;
2279   struct guestfs_aug_match_ret ret;
2280 };
2281
2282 static void aug_match_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2283 {
2284   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2285   struct aug_match_ctx *ctx = (struct aug_match_ctx *) data;
2286
2287   /* This should definitely not happen. */
2288   if (ctx->cb_sequence != 0) {
2289     ctx->cb_sequence = 9999;
2290     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_match");
2291     return;
2292   }
2293
2294   ml->main_loop_quit (ml, g);
2295
2296   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2297     error (g, "%s: failed to parse reply header", "guestfs_aug_match");
2298     return;
2299   }
2300   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2301     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2302       error (g, "%s: failed to parse reply error", "guestfs_aug_match");
2303       return;
2304     }
2305     goto done;
2306   }
2307   if (!xdr_guestfs_aug_match_ret (xdr, &ctx->ret)) {
2308     error (g, "%s: failed to parse reply", "guestfs_aug_match");
2309     return;
2310   }
2311  done:
2312   ctx->cb_sequence = 1;
2313 }
2314
2315 char **guestfs_aug_match (guestfs_h *g,
2316                 const char *path)
2317 {
2318   struct guestfs_aug_match_args args;
2319   struct aug_match_ctx ctx;
2320   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2321   int serial;
2322
2323   if (check_state (g, "guestfs_aug_match") == -1) return NULL;
2324   guestfs_set_busy (g);
2325
2326   memset (&ctx, 0, sizeof ctx);
2327
2328   args.path = (char *) path;
2329   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MATCH,
2330         (xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args);
2331   if (serial == -1) {
2332     guestfs_end_busy (g);
2333     return NULL;
2334   }
2335
2336   guestfs__switch_to_receiving (g);
2337   ctx.cb_sequence = 0;
2338   guestfs_set_reply_callback (g, aug_match_reply_cb, &ctx);
2339   (void) ml->main_loop_run (ml, g);
2340   guestfs_set_reply_callback (g, NULL, NULL);
2341   if (ctx.cb_sequence != 1) {
2342     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match");
2343     guestfs_end_busy (g);
2344     return NULL;
2345   }
2346
2347   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1) {
2348     guestfs_end_busy (g);
2349     return NULL;
2350   }
2351
2352   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2353     error (g, "%s", ctx.err.error_message);
2354     free (ctx.err.error_message);
2355     guestfs_end_busy (g);
2356     return NULL;
2357   }
2358
2359   guestfs_end_busy (g);
2360   /* caller will free this, but we need to add a NULL entry */
2361   ctx.ret.matches.matches_val =
2362     safe_realloc (g, ctx.ret.matches.matches_val,
2363                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2364   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2365   return ctx.ret.matches.matches_val;
2366 }
2367
2368 struct aug_save_ctx {
2369   /* This flag is set by the callbacks, so we know we've done
2370    * the callbacks as expected, and in the right sequence.
2371    * 0 = not called, 1 = reply_cb called.
2372    */
2373   int cb_sequence;
2374   struct guestfs_message_header hdr;
2375   struct guestfs_message_error err;
2376 };
2377
2378 static void aug_save_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2379 {
2380   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2381   struct aug_save_ctx *ctx = (struct aug_save_ctx *) data;
2382
2383   /* This should definitely not happen. */
2384   if (ctx->cb_sequence != 0) {
2385     ctx->cb_sequence = 9999;
2386     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_save");
2387     return;
2388   }
2389
2390   ml->main_loop_quit (ml, g);
2391
2392   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2393     error (g, "%s: failed to parse reply header", "guestfs_aug_save");
2394     return;
2395   }
2396   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2397     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2398       error (g, "%s: failed to parse reply error", "guestfs_aug_save");
2399       return;
2400     }
2401     goto done;
2402   }
2403  done:
2404   ctx->cb_sequence = 1;
2405 }
2406
2407 int guestfs_aug_save (guestfs_h *g)
2408 {
2409   struct aug_save_ctx ctx;
2410   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2411   int serial;
2412
2413   if (check_state (g, "guestfs_aug_save") == -1) return -1;
2414   guestfs_set_busy (g);
2415
2416   memset (&ctx, 0, sizeof ctx);
2417
2418   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
2419   if (serial == -1) {
2420     guestfs_end_busy (g);
2421     return -1;
2422   }
2423
2424   guestfs__switch_to_receiving (g);
2425   ctx.cb_sequence = 0;
2426   guestfs_set_reply_callback (g, aug_save_reply_cb, &ctx);
2427   (void) ml->main_loop_run (ml, g);
2428   guestfs_set_reply_callback (g, NULL, NULL);
2429   if (ctx.cb_sequence != 1) {
2430     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save");
2431     guestfs_end_busy (g);
2432     return -1;
2433   }
2434
2435   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1) {
2436     guestfs_end_busy (g);
2437     return -1;
2438   }
2439
2440   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2441     error (g, "%s", ctx.err.error_message);
2442     free (ctx.err.error_message);
2443     guestfs_end_busy (g);
2444     return -1;
2445   }
2446
2447   guestfs_end_busy (g);
2448   return 0;
2449 }
2450
2451 struct aug_load_ctx {
2452   /* This flag is set by the callbacks, so we know we've done
2453    * the callbacks as expected, and in the right sequence.
2454    * 0 = not called, 1 = reply_cb called.
2455    */
2456   int cb_sequence;
2457   struct guestfs_message_header hdr;
2458   struct guestfs_message_error err;
2459 };
2460
2461 static void aug_load_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2462 {
2463   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2464   struct aug_load_ctx *ctx = (struct aug_load_ctx *) data;
2465
2466   /* This should definitely not happen. */
2467   if (ctx->cb_sequence != 0) {
2468     ctx->cb_sequence = 9999;
2469     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_load");
2470     return;
2471   }
2472
2473   ml->main_loop_quit (ml, g);
2474
2475   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2476     error (g, "%s: failed to parse reply header", "guestfs_aug_load");
2477     return;
2478   }
2479   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2480     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2481       error (g, "%s: failed to parse reply error", "guestfs_aug_load");
2482       return;
2483     }
2484     goto done;
2485   }
2486  done:
2487   ctx->cb_sequence = 1;
2488 }
2489
2490 int guestfs_aug_load (guestfs_h *g)
2491 {
2492   struct aug_load_ctx ctx;
2493   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2494   int serial;
2495
2496   if (check_state (g, "guestfs_aug_load") == -1) return -1;
2497   guestfs_set_busy (g);
2498
2499   memset (&ctx, 0, sizeof ctx);
2500
2501   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
2502   if (serial == -1) {
2503     guestfs_end_busy (g);
2504     return -1;
2505   }
2506
2507   guestfs__switch_to_receiving (g);
2508   ctx.cb_sequence = 0;
2509   guestfs_set_reply_callback (g, aug_load_reply_cb, &ctx);
2510   (void) ml->main_loop_run (ml, g);
2511   guestfs_set_reply_callback (g, NULL, NULL);
2512   if (ctx.cb_sequence != 1) {
2513     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load");
2514     guestfs_end_busy (g);
2515     return -1;
2516   }
2517
2518   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1) {
2519     guestfs_end_busy (g);
2520     return -1;
2521   }
2522
2523   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2524     error (g, "%s", ctx.err.error_message);
2525     free (ctx.err.error_message);
2526     guestfs_end_busy (g);
2527     return -1;
2528   }
2529
2530   guestfs_end_busy (g);
2531   return 0;
2532 }
2533
2534 struct aug_ls_ctx {
2535   /* This flag is set by the callbacks, so we know we've done
2536    * the callbacks as expected, and in the right sequence.
2537    * 0 = not called, 1 = reply_cb called.
2538    */
2539   int cb_sequence;
2540   struct guestfs_message_header hdr;
2541   struct guestfs_message_error err;
2542   struct guestfs_aug_ls_ret ret;
2543 };
2544
2545 static void aug_ls_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2546 {
2547   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2548   struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data;
2549
2550   /* This should definitely not happen. */
2551   if (ctx->cb_sequence != 0) {
2552     ctx->cb_sequence = 9999;
2553     error (g, "%s: internal error: reply callback called twice", "guestfs_aug_ls");
2554     return;
2555   }
2556
2557   ml->main_loop_quit (ml, g);
2558
2559   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2560     error (g, "%s: failed to parse reply header", "guestfs_aug_ls");
2561     return;
2562   }
2563   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2564     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2565       error (g, "%s: failed to parse reply error", "guestfs_aug_ls");
2566       return;
2567     }
2568     goto done;
2569   }
2570   if (!xdr_guestfs_aug_ls_ret (xdr, &ctx->ret)) {
2571     error (g, "%s: failed to parse reply", "guestfs_aug_ls");
2572     return;
2573   }
2574  done:
2575   ctx->cb_sequence = 1;
2576 }
2577
2578 char **guestfs_aug_ls (guestfs_h *g,
2579                 const char *path)
2580 {
2581   struct guestfs_aug_ls_args args;
2582   struct aug_ls_ctx ctx;
2583   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2584   int serial;
2585
2586   if (check_state (g, "guestfs_aug_ls") == -1) return NULL;
2587   guestfs_set_busy (g);
2588
2589   memset (&ctx, 0, sizeof ctx);
2590
2591   args.path = (char *) path;
2592   serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LS,
2593         (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
2594   if (serial == -1) {
2595     guestfs_end_busy (g);
2596     return NULL;
2597   }
2598
2599   guestfs__switch_to_receiving (g);
2600   ctx.cb_sequence = 0;
2601   guestfs_set_reply_callback (g, aug_ls_reply_cb, &ctx);
2602   (void) ml->main_loop_run (ml, g);
2603   guestfs_set_reply_callback (g, NULL, NULL);
2604   if (ctx.cb_sequence != 1) {
2605     error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls");
2606     guestfs_end_busy (g);
2607     return NULL;
2608   }
2609
2610   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LS, serial) == -1) {
2611     guestfs_end_busy (g);
2612     return NULL;
2613   }
2614
2615   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2616     error (g, "%s", ctx.err.error_message);
2617     free (ctx.err.error_message);
2618     guestfs_end_busy (g);
2619     return NULL;
2620   }
2621
2622   guestfs_end_busy (g);
2623   /* caller will free this, but we need to add a NULL entry */
2624   ctx.ret.matches.matches_val =
2625     safe_realloc (g, ctx.ret.matches.matches_val,
2626                   sizeof (char *) * (ctx.ret.matches.matches_len + 1));
2627   ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL;
2628   return ctx.ret.matches.matches_val;
2629 }
2630
2631 struct rm_ctx {
2632   /* This flag is set by the callbacks, so we know we've done
2633    * the callbacks as expected, and in the right sequence.
2634    * 0 = not called, 1 = reply_cb called.
2635    */
2636   int cb_sequence;
2637   struct guestfs_message_header hdr;
2638   struct guestfs_message_error err;
2639 };
2640
2641 static void rm_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2642 {
2643   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2644   struct rm_ctx *ctx = (struct rm_ctx *) data;
2645
2646   /* This should definitely not happen. */
2647   if (ctx->cb_sequence != 0) {
2648     ctx->cb_sequence = 9999;
2649     error (g, "%s: internal error: reply callback called twice", "guestfs_rm");
2650     return;
2651   }
2652
2653   ml->main_loop_quit (ml, g);
2654
2655   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2656     error (g, "%s: failed to parse reply header", "guestfs_rm");
2657     return;
2658   }
2659   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2660     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2661       error (g, "%s: failed to parse reply error", "guestfs_rm");
2662       return;
2663     }
2664     goto done;
2665   }
2666  done:
2667   ctx->cb_sequence = 1;
2668 }
2669
2670 int guestfs_rm (guestfs_h *g,
2671                 const char *path)
2672 {
2673   struct guestfs_rm_args args;
2674   struct rm_ctx ctx;
2675   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2676   int serial;
2677
2678   if (check_state (g, "guestfs_rm") == -1) return -1;
2679   guestfs_set_busy (g);
2680
2681   memset (&ctx, 0, sizeof ctx);
2682
2683   args.path = (char *) path;
2684   serial = guestfs__send_sync (g, GUESTFS_PROC_RM,
2685         (xdrproc_t) xdr_guestfs_rm_args, (char *) &args);
2686   if (serial == -1) {
2687     guestfs_end_busy (g);
2688     return -1;
2689   }
2690
2691   guestfs__switch_to_receiving (g);
2692   ctx.cb_sequence = 0;
2693   guestfs_set_reply_callback (g, rm_reply_cb, &ctx);
2694   (void) ml->main_loop_run (ml, g);
2695   guestfs_set_reply_callback (g, NULL, NULL);
2696   if (ctx.cb_sequence != 1) {
2697     error (g, "%s reply failed, see earlier error messages", "guestfs_rm");
2698     guestfs_end_busy (g);
2699     return -1;
2700   }
2701
2702   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM, serial) == -1) {
2703     guestfs_end_busy (g);
2704     return -1;
2705   }
2706
2707   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2708     error (g, "%s", ctx.err.error_message);
2709     free (ctx.err.error_message);
2710     guestfs_end_busy (g);
2711     return -1;
2712   }
2713
2714   guestfs_end_busy (g);
2715   return 0;
2716 }
2717
2718 struct rmdir_ctx {
2719   /* This flag is set by the callbacks, so we know we've done
2720    * the callbacks as expected, and in the right sequence.
2721    * 0 = not called, 1 = reply_cb called.
2722    */
2723   int cb_sequence;
2724   struct guestfs_message_header hdr;
2725   struct guestfs_message_error err;
2726 };
2727
2728 static void rmdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2729 {
2730   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2731   struct rmdir_ctx *ctx = (struct rmdir_ctx *) data;
2732
2733   /* This should definitely not happen. */
2734   if (ctx->cb_sequence != 0) {
2735     ctx->cb_sequence = 9999;
2736     error (g, "%s: internal error: reply callback called twice", "guestfs_rmdir");
2737     return;
2738   }
2739
2740   ml->main_loop_quit (ml, g);
2741
2742   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2743     error (g, "%s: failed to parse reply header", "guestfs_rmdir");
2744     return;
2745   }
2746   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2747     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2748       error (g, "%s: failed to parse reply error", "guestfs_rmdir");
2749       return;
2750     }
2751     goto done;
2752   }
2753  done:
2754   ctx->cb_sequence = 1;
2755 }
2756
2757 int guestfs_rmdir (guestfs_h *g,
2758                 const char *path)
2759 {
2760   struct guestfs_rmdir_args args;
2761   struct rmdir_ctx ctx;
2762   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2763   int serial;
2764
2765   if (check_state (g, "guestfs_rmdir") == -1) return -1;
2766   guestfs_set_busy (g);
2767
2768   memset (&ctx, 0, sizeof ctx);
2769
2770   args.path = (char *) path;
2771   serial = guestfs__send_sync (g, GUESTFS_PROC_RMDIR,
2772         (xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args);
2773   if (serial == -1) {
2774     guestfs_end_busy (g);
2775     return -1;
2776   }
2777
2778   guestfs__switch_to_receiving (g);
2779   ctx.cb_sequence = 0;
2780   guestfs_set_reply_callback (g, rmdir_reply_cb, &ctx);
2781   (void) ml->main_loop_run (ml, g);
2782   guestfs_set_reply_callback (g, NULL, NULL);
2783   if (ctx.cb_sequence != 1) {
2784     error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir");
2785     guestfs_end_busy (g);
2786     return -1;
2787   }
2788
2789   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RMDIR, serial) == -1) {
2790     guestfs_end_busy (g);
2791     return -1;
2792   }
2793
2794   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2795     error (g, "%s", ctx.err.error_message);
2796     free (ctx.err.error_message);
2797     guestfs_end_busy (g);
2798     return -1;
2799   }
2800
2801   guestfs_end_busy (g);
2802   return 0;
2803 }
2804
2805 struct rm_rf_ctx {
2806   /* This flag is set by the callbacks, so we know we've done
2807    * the callbacks as expected, and in the right sequence.
2808    * 0 = not called, 1 = reply_cb called.
2809    */
2810   int cb_sequence;
2811   struct guestfs_message_header hdr;
2812   struct guestfs_message_error err;
2813 };
2814
2815 static void rm_rf_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2816 {
2817   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2818   struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data;
2819
2820   /* This should definitely not happen. */
2821   if (ctx->cb_sequence != 0) {
2822     ctx->cb_sequence = 9999;
2823     error (g, "%s: internal error: reply callback called twice", "guestfs_rm_rf");
2824     return;
2825   }
2826
2827   ml->main_loop_quit (ml, g);
2828
2829   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2830     error (g, "%s: failed to parse reply header", "guestfs_rm_rf");
2831     return;
2832   }
2833   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2834     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2835       error (g, "%s: failed to parse reply error", "guestfs_rm_rf");
2836       return;
2837     }
2838     goto done;
2839   }
2840  done:
2841   ctx->cb_sequence = 1;
2842 }
2843
2844 int guestfs_rm_rf (guestfs_h *g,
2845                 const char *path)
2846 {
2847   struct guestfs_rm_rf_args args;
2848   struct rm_rf_ctx ctx;
2849   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2850   int serial;
2851
2852   if (check_state (g, "guestfs_rm_rf") == -1) return -1;
2853   guestfs_set_busy (g);
2854
2855   memset (&ctx, 0, sizeof ctx);
2856
2857   args.path = (char *) path;
2858   serial = guestfs__send_sync (g, GUESTFS_PROC_RM_RF,
2859         (xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args);
2860   if (serial == -1) {
2861     guestfs_end_busy (g);
2862     return -1;
2863   }
2864
2865   guestfs__switch_to_receiving (g);
2866   ctx.cb_sequence = 0;
2867   guestfs_set_reply_callback (g, rm_rf_reply_cb, &ctx);
2868   (void) ml->main_loop_run (ml, g);
2869   guestfs_set_reply_callback (g, NULL, NULL);
2870   if (ctx.cb_sequence != 1) {
2871     error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf");
2872     guestfs_end_busy (g);
2873     return -1;
2874   }
2875
2876   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM_RF, serial) == -1) {
2877     guestfs_end_busy (g);
2878     return -1;
2879   }
2880
2881   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2882     error (g, "%s", ctx.err.error_message);
2883     free (ctx.err.error_message);
2884     guestfs_end_busy (g);
2885     return -1;
2886   }
2887
2888   guestfs_end_busy (g);
2889   return 0;
2890 }
2891
2892 struct mkdir_ctx {
2893   /* This flag is set by the callbacks, so we know we've done
2894    * the callbacks as expected, and in the right sequence.
2895    * 0 = not called, 1 = reply_cb called.
2896    */
2897   int cb_sequence;
2898   struct guestfs_message_header hdr;
2899   struct guestfs_message_error err;
2900 };
2901
2902 static void mkdir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2903 {
2904   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2905   struct mkdir_ctx *ctx = (struct mkdir_ctx *) data;
2906
2907   /* This should definitely not happen. */
2908   if (ctx->cb_sequence != 0) {
2909     ctx->cb_sequence = 9999;
2910     error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir");
2911     return;
2912   }
2913
2914   ml->main_loop_quit (ml, g);
2915
2916   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
2917     error (g, "%s: failed to parse reply header", "guestfs_mkdir");
2918     return;
2919   }
2920   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
2921     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
2922       error (g, "%s: failed to parse reply error", "guestfs_mkdir");
2923       return;
2924     }
2925     goto done;
2926   }
2927  done:
2928   ctx->cb_sequence = 1;
2929 }
2930
2931 int guestfs_mkdir (guestfs_h *g,
2932                 const char *path)
2933 {
2934   struct guestfs_mkdir_args args;
2935   struct mkdir_ctx ctx;
2936   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2937   int serial;
2938
2939   if (check_state (g, "guestfs_mkdir") == -1) return -1;
2940   guestfs_set_busy (g);
2941
2942   memset (&ctx, 0, sizeof ctx);
2943
2944   args.path = (char *) path;
2945   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR,
2946         (xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args);
2947   if (serial == -1) {
2948     guestfs_end_busy (g);
2949     return -1;
2950   }
2951
2952   guestfs__switch_to_receiving (g);
2953   ctx.cb_sequence = 0;
2954   guestfs_set_reply_callback (g, mkdir_reply_cb, &ctx);
2955   (void) ml->main_loop_run (ml, g);
2956   guestfs_set_reply_callback (g, NULL, NULL);
2957   if (ctx.cb_sequence != 1) {
2958     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir");
2959     guestfs_end_busy (g);
2960     return -1;
2961   }
2962
2963   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR, serial) == -1) {
2964     guestfs_end_busy (g);
2965     return -1;
2966   }
2967
2968   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
2969     error (g, "%s", ctx.err.error_message);
2970     free (ctx.err.error_message);
2971     guestfs_end_busy (g);
2972     return -1;
2973   }
2974
2975   guestfs_end_busy (g);
2976   return 0;
2977 }
2978
2979 struct mkdir_p_ctx {
2980   /* This flag is set by the callbacks, so we know we've done
2981    * the callbacks as expected, and in the right sequence.
2982    * 0 = not called, 1 = reply_cb called.
2983    */
2984   int cb_sequence;
2985   struct guestfs_message_header hdr;
2986   struct guestfs_message_error err;
2987 };
2988
2989 static void mkdir_p_reply_cb (guestfs_h *g, void *data, XDR *xdr)
2990 {
2991   guestfs_main_loop *ml = guestfs_get_main_loop (g);
2992   struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data;
2993
2994   /* This should definitely not happen. */
2995   if (ctx->cb_sequence != 0) {
2996     ctx->cb_sequence = 9999;
2997     error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir_p");
2998     return;
2999   }
3000
3001   ml->main_loop_quit (ml, g);
3002
3003   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3004     error (g, "%s: failed to parse reply header", "guestfs_mkdir_p");
3005     return;
3006   }
3007   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3008     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3009       error (g, "%s: failed to parse reply error", "guestfs_mkdir_p");
3010       return;
3011     }
3012     goto done;
3013   }
3014  done:
3015   ctx->cb_sequence = 1;
3016 }
3017
3018 int guestfs_mkdir_p (guestfs_h *g,
3019                 const char *path)
3020 {
3021   struct guestfs_mkdir_p_args args;
3022   struct mkdir_p_ctx ctx;
3023   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3024   int serial;
3025
3026   if (check_state (g, "guestfs_mkdir_p") == -1) return -1;
3027   guestfs_set_busy (g);
3028
3029   memset (&ctx, 0, sizeof ctx);
3030
3031   args.path = (char *) path;
3032   serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR_P,
3033         (xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args);
3034   if (serial == -1) {
3035     guestfs_end_busy (g);
3036     return -1;
3037   }
3038
3039   guestfs__switch_to_receiving (g);
3040   ctx.cb_sequence = 0;
3041   guestfs_set_reply_callback (g, mkdir_p_reply_cb, &ctx);
3042   (void) ml->main_loop_run (ml, g);
3043   guestfs_set_reply_callback (g, NULL, NULL);
3044   if (ctx.cb_sequence != 1) {
3045     error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p");
3046     guestfs_end_busy (g);
3047     return -1;
3048   }
3049
3050   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1) {
3051     guestfs_end_busy (g);
3052     return -1;
3053   }
3054
3055   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3056     error (g, "%s", ctx.err.error_message);
3057     free (ctx.err.error_message);
3058     guestfs_end_busy (g);
3059     return -1;
3060   }
3061
3062   guestfs_end_busy (g);
3063   return 0;
3064 }
3065
3066 struct chmod_ctx {
3067   /* This flag is set by the callbacks, so we know we've done
3068    * the callbacks as expected, and in the right sequence.
3069    * 0 = not called, 1 = reply_cb called.
3070    */
3071   int cb_sequence;
3072   struct guestfs_message_header hdr;
3073   struct guestfs_message_error err;
3074 };
3075
3076 static void chmod_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3077 {
3078   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3079   struct chmod_ctx *ctx = (struct chmod_ctx *) data;
3080
3081   /* This should definitely not happen. */
3082   if (ctx->cb_sequence != 0) {
3083     ctx->cb_sequence = 9999;
3084     error (g, "%s: internal error: reply callback called twice", "guestfs_chmod");
3085     return;
3086   }
3087
3088   ml->main_loop_quit (ml, g);
3089
3090   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3091     error (g, "%s: failed to parse reply header", "guestfs_chmod");
3092     return;
3093   }
3094   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3095     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3096       error (g, "%s: failed to parse reply error", "guestfs_chmod");
3097       return;
3098     }
3099     goto done;
3100   }
3101  done:
3102   ctx->cb_sequence = 1;
3103 }
3104
3105 int guestfs_chmod (guestfs_h *g,
3106                 int mode,
3107                 const char *path)
3108 {
3109   struct guestfs_chmod_args args;
3110   struct chmod_ctx ctx;
3111   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3112   int serial;
3113
3114   if (check_state (g, "guestfs_chmod") == -1) return -1;
3115   guestfs_set_busy (g);
3116
3117   memset (&ctx, 0, sizeof ctx);
3118
3119   args.mode = mode;
3120   args.path = (char *) path;
3121   serial = guestfs__send_sync (g, GUESTFS_PROC_CHMOD,
3122         (xdrproc_t) xdr_guestfs_chmod_args, (char *) &args);
3123   if (serial == -1) {
3124     guestfs_end_busy (g);
3125     return -1;
3126   }
3127
3128   guestfs__switch_to_receiving (g);
3129   ctx.cb_sequence = 0;
3130   guestfs_set_reply_callback (g, chmod_reply_cb, &ctx);
3131   (void) ml->main_loop_run (ml, g);
3132   guestfs_set_reply_callback (g, NULL, NULL);
3133   if (ctx.cb_sequence != 1) {
3134     error (g, "%s reply failed, see earlier error messages", "guestfs_chmod");
3135     guestfs_end_busy (g);
3136     return -1;
3137   }
3138
3139   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHMOD, serial) == -1) {
3140     guestfs_end_busy (g);
3141     return -1;
3142   }
3143
3144   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3145     error (g, "%s", ctx.err.error_message);
3146     free (ctx.err.error_message);
3147     guestfs_end_busy (g);
3148     return -1;
3149   }
3150
3151   guestfs_end_busy (g);
3152   return 0;
3153 }
3154
3155 struct chown_ctx {
3156   /* This flag is set by the callbacks, so we know we've done
3157    * the callbacks as expected, and in the right sequence.
3158    * 0 = not called, 1 = reply_cb called.
3159    */
3160   int cb_sequence;
3161   struct guestfs_message_header hdr;
3162   struct guestfs_message_error err;
3163 };
3164
3165 static void chown_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3166 {
3167   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3168   struct chown_ctx *ctx = (struct chown_ctx *) data;
3169
3170   /* This should definitely not happen. */
3171   if (ctx->cb_sequence != 0) {
3172     ctx->cb_sequence = 9999;
3173     error (g, "%s: internal error: reply callback called twice", "guestfs_chown");
3174     return;
3175   }
3176
3177   ml->main_loop_quit (ml, g);
3178
3179   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3180     error (g, "%s: failed to parse reply header", "guestfs_chown");
3181     return;
3182   }
3183   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3184     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3185       error (g, "%s: failed to parse reply error", "guestfs_chown");
3186       return;
3187     }
3188     goto done;
3189   }
3190  done:
3191   ctx->cb_sequence = 1;
3192 }
3193
3194 int guestfs_chown (guestfs_h *g,
3195                 int owner,
3196                 int group,
3197                 const char *path)
3198 {
3199   struct guestfs_chown_args args;
3200   struct chown_ctx ctx;
3201   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3202   int serial;
3203
3204   if (check_state (g, "guestfs_chown") == -1) return -1;
3205   guestfs_set_busy (g);
3206
3207   memset (&ctx, 0, sizeof ctx);
3208
3209   args.owner = owner;
3210   args.group = group;
3211   args.path = (char *) path;
3212   serial = guestfs__send_sync (g, GUESTFS_PROC_CHOWN,
3213         (xdrproc_t) xdr_guestfs_chown_args, (char *) &args);
3214   if (serial == -1) {
3215     guestfs_end_busy (g);
3216     return -1;
3217   }
3218
3219   guestfs__switch_to_receiving (g);
3220   ctx.cb_sequence = 0;
3221   guestfs_set_reply_callback (g, chown_reply_cb, &ctx);
3222   (void) ml->main_loop_run (ml, g);
3223   guestfs_set_reply_callback (g, NULL, NULL);
3224   if (ctx.cb_sequence != 1) {
3225     error (g, "%s reply failed, see earlier error messages", "guestfs_chown");
3226     guestfs_end_busy (g);
3227     return -1;
3228   }
3229
3230   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHOWN, serial) == -1) {
3231     guestfs_end_busy (g);
3232     return -1;
3233   }
3234
3235   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3236     error (g, "%s", ctx.err.error_message);
3237     free (ctx.err.error_message);
3238     guestfs_end_busy (g);
3239     return -1;
3240   }
3241
3242   guestfs_end_busy (g);
3243   return 0;
3244 }
3245
3246 struct exists_ctx {
3247   /* This flag is set by the callbacks, so we know we've done
3248    * the callbacks as expected, and in the right sequence.
3249    * 0 = not called, 1 = reply_cb called.
3250    */
3251   int cb_sequence;
3252   struct guestfs_message_header hdr;
3253   struct guestfs_message_error err;
3254   struct guestfs_exists_ret ret;
3255 };
3256
3257 static void exists_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3258 {
3259   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3260   struct exists_ctx *ctx = (struct exists_ctx *) data;
3261
3262   /* This should definitely not happen. */
3263   if (ctx->cb_sequence != 0) {
3264     ctx->cb_sequence = 9999;
3265     error (g, "%s: internal error: reply callback called twice", "guestfs_exists");
3266     return;
3267   }
3268
3269   ml->main_loop_quit (ml, g);
3270
3271   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3272     error (g, "%s: failed to parse reply header", "guestfs_exists");
3273     return;
3274   }
3275   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3276     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3277       error (g, "%s: failed to parse reply error", "guestfs_exists");
3278       return;
3279     }
3280     goto done;
3281   }
3282   if (!xdr_guestfs_exists_ret (xdr, &ctx->ret)) {
3283     error (g, "%s: failed to parse reply", "guestfs_exists");
3284     return;
3285   }
3286  done:
3287   ctx->cb_sequence = 1;
3288 }
3289
3290 int guestfs_exists (guestfs_h *g,
3291                 const char *path)
3292 {
3293   struct guestfs_exists_args args;
3294   struct exists_ctx ctx;
3295   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3296   int serial;
3297
3298   if (check_state (g, "guestfs_exists") == -1) return -1;
3299   guestfs_set_busy (g);
3300
3301   memset (&ctx, 0, sizeof ctx);
3302
3303   args.path = (char *) path;
3304   serial = guestfs__send_sync (g, GUESTFS_PROC_EXISTS,
3305         (xdrproc_t) xdr_guestfs_exists_args, (char *) &args);
3306   if (serial == -1) {
3307     guestfs_end_busy (g);
3308     return -1;
3309   }
3310
3311   guestfs__switch_to_receiving (g);
3312   ctx.cb_sequence = 0;
3313   guestfs_set_reply_callback (g, exists_reply_cb, &ctx);
3314   (void) ml->main_loop_run (ml, g);
3315   guestfs_set_reply_callback (g, NULL, NULL);
3316   if (ctx.cb_sequence != 1) {
3317     error (g, "%s reply failed, see earlier error messages", "guestfs_exists");
3318     guestfs_end_busy (g);
3319     return -1;
3320   }
3321
3322   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EXISTS, serial) == -1) {
3323     guestfs_end_busy (g);
3324     return -1;
3325   }
3326
3327   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3328     error (g, "%s", ctx.err.error_message);
3329     free (ctx.err.error_message);
3330     guestfs_end_busy (g);
3331     return -1;
3332   }
3333
3334   guestfs_end_busy (g);
3335   return ctx.ret.existsflag;
3336 }
3337
3338 struct is_file_ctx {
3339   /* This flag is set by the callbacks, so we know we've done
3340    * the callbacks as expected, and in the right sequence.
3341    * 0 = not called, 1 = reply_cb called.
3342    */
3343   int cb_sequence;
3344   struct guestfs_message_header hdr;
3345   struct guestfs_message_error err;
3346   struct guestfs_is_file_ret ret;
3347 };
3348
3349 static void is_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3350 {
3351   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3352   struct is_file_ctx *ctx = (struct is_file_ctx *) data;
3353
3354   /* This should definitely not happen. */
3355   if (ctx->cb_sequence != 0) {
3356     ctx->cb_sequence = 9999;
3357     error (g, "%s: internal error: reply callback called twice", "guestfs_is_file");
3358     return;
3359   }
3360
3361   ml->main_loop_quit (ml, g);
3362
3363   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3364     error (g, "%s: failed to parse reply header", "guestfs_is_file");
3365     return;
3366   }
3367   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3368     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3369       error (g, "%s: failed to parse reply error", "guestfs_is_file");
3370       return;
3371     }
3372     goto done;
3373   }
3374   if (!xdr_guestfs_is_file_ret (xdr, &ctx->ret)) {
3375     error (g, "%s: failed to parse reply", "guestfs_is_file");
3376     return;
3377   }
3378  done:
3379   ctx->cb_sequence = 1;
3380 }
3381
3382 int guestfs_is_file (guestfs_h *g,
3383                 const char *path)
3384 {
3385   struct guestfs_is_file_args args;
3386   struct is_file_ctx ctx;
3387   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3388   int serial;
3389
3390   if (check_state (g, "guestfs_is_file") == -1) return -1;
3391   guestfs_set_busy (g);
3392
3393   memset (&ctx, 0, sizeof ctx);
3394
3395   args.path = (char *) path;
3396   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_FILE,
3397         (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args);
3398   if (serial == -1) {
3399     guestfs_end_busy (g);
3400     return -1;
3401   }
3402
3403   guestfs__switch_to_receiving (g);
3404   ctx.cb_sequence = 0;
3405   guestfs_set_reply_callback (g, is_file_reply_cb, &ctx);
3406   (void) ml->main_loop_run (ml, g);
3407   guestfs_set_reply_callback (g, NULL, NULL);
3408   if (ctx.cb_sequence != 1) {
3409     error (g, "%s reply failed, see earlier error messages", "guestfs_is_file");
3410     guestfs_end_busy (g);
3411     return -1;
3412   }
3413
3414   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_FILE, serial) == -1) {
3415     guestfs_end_busy (g);
3416     return -1;
3417   }
3418
3419   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3420     error (g, "%s", ctx.err.error_message);
3421     free (ctx.err.error_message);
3422     guestfs_end_busy (g);
3423     return -1;
3424   }
3425
3426   guestfs_end_busy (g);
3427   return ctx.ret.fileflag;
3428 }
3429
3430 struct is_dir_ctx {
3431   /* This flag is set by the callbacks, so we know we've done
3432    * the callbacks as expected, and in the right sequence.
3433    * 0 = not called, 1 = reply_cb called.
3434    */
3435   int cb_sequence;
3436   struct guestfs_message_header hdr;
3437   struct guestfs_message_error err;
3438   struct guestfs_is_dir_ret ret;
3439 };
3440
3441 static void is_dir_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3442 {
3443   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3444   struct is_dir_ctx *ctx = (struct is_dir_ctx *) data;
3445
3446   /* This should definitely not happen. */
3447   if (ctx->cb_sequence != 0) {
3448     ctx->cb_sequence = 9999;
3449     error (g, "%s: internal error: reply callback called twice", "guestfs_is_dir");
3450     return;
3451   }
3452
3453   ml->main_loop_quit (ml, g);
3454
3455   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3456     error (g, "%s: failed to parse reply header", "guestfs_is_dir");
3457     return;
3458   }
3459   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3460     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3461       error (g, "%s: failed to parse reply error", "guestfs_is_dir");
3462       return;
3463     }
3464     goto done;
3465   }
3466   if (!xdr_guestfs_is_dir_ret (xdr, &ctx->ret)) {
3467     error (g, "%s: failed to parse reply", "guestfs_is_dir");
3468     return;
3469   }
3470  done:
3471   ctx->cb_sequence = 1;
3472 }
3473
3474 int guestfs_is_dir (guestfs_h *g,
3475                 const char *path)
3476 {
3477   struct guestfs_is_dir_args args;
3478   struct is_dir_ctx ctx;
3479   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3480   int serial;
3481
3482   if (check_state (g, "guestfs_is_dir") == -1) return -1;
3483   guestfs_set_busy (g);
3484
3485   memset (&ctx, 0, sizeof ctx);
3486
3487   args.path = (char *) path;
3488   serial = guestfs__send_sync (g, GUESTFS_PROC_IS_DIR,
3489         (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args);
3490   if (serial == -1) {
3491     guestfs_end_busy (g);
3492     return -1;
3493   }
3494
3495   guestfs__switch_to_receiving (g);
3496   ctx.cb_sequence = 0;
3497   guestfs_set_reply_callback (g, is_dir_reply_cb, &ctx);
3498   (void) ml->main_loop_run (ml, g);
3499   guestfs_set_reply_callback (g, NULL, NULL);
3500   if (ctx.cb_sequence != 1) {
3501     error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir");
3502     guestfs_end_busy (g);
3503     return -1;
3504   }
3505
3506   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_DIR, serial) == -1) {
3507     guestfs_end_busy (g);
3508     return -1;
3509   }
3510
3511   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3512     error (g, "%s", ctx.err.error_message);
3513     free (ctx.err.error_message);
3514     guestfs_end_busy (g);
3515     return -1;
3516   }
3517
3518   guestfs_end_busy (g);
3519   return ctx.ret.dirflag;
3520 }
3521
3522 struct pvcreate_ctx {
3523   /* This flag is set by the callbacks, so we know we've done
3524    * the callbacks as expected, and in the right sequence.
3525    * 0 = not called, 1 = reply_cb called.
3526    */
3527   int cb_sequence;
3528   struct guestfs_message_header hdr;
3529   struct guestfs_message_error err;
3530 };
3531
3532 static void pvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3533 {
3534   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3535   struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data;
3536
3537   /* This should definitely not happen. */
3538   if (ctx->cb_sequence != 0) {
3539     ctx->cb_sequence = 9999;
3540     error (g, "%s: internal error: reply callback called twice", "guestfs_pvcreate");
3541     return;
3542   }
3543
3544   ml->main_loop_quit (ml, g);
3545
3546   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3547     error (g, "%s: failed to parse reply header", "guestfs_pvcreate");
3548     return;
3549   }
3550   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3551     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3552       error (g, "%s: failed to parse reply error", "guestfs_pvcreate");
3553       return;
3554     }
3555     goto done;
3556   }
3557  done:
3558   ctx->cb_sequence = 1;
3559 }
3560
3561 int guestfs_pvcreate (guestfs_h *g,
3562                 const char *device)
3563 {
3564   struct guestfs_pvcreate_args args;
3565   struct pvcreate_ctx ctx;
3566   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3567   int serial;
3568
3569   if (check_state (g, "guestfs_pvcreate") == -1) return -1;
3570   guestfs_set_busy (g);
3571
3572   memset (&ctx, 0, sizeof ctx);
3573
3574   args.device = (char *) device;
3575   serial = guestfs__send_sync (g, GUESTFS_PROC_PVCREATE,
3576         (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args);
3577   if (serial == -1) {
3578     guestfs_end_busy (g);
3579     return -1;
3580   }
3581
3582   guestfs__switch_to_receiving (g);
3583   ctx.cb_sequence = 0;
3584   guestfs_set_reply_callback (g, pvcreate_reply_cb, &ctx);
3585   (void) ml->main_loop_run (ml, g);
3586   guestfs_set_reply_callback (g, NULL, NULL);
3587   if (ctx.cb_sequence != 1) {
3588     error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate");
3589     guestfs_end_busy (g);
3590     return -1;
3591   }
3592
3593   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVCREATE, serial) == -1) {
3594     guestfs_end_busy (g);
3595     return -1;
3596   }
3597
3598   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3599     error (g, "%s", ctx.err.error_message);
3600     free (ctx.err.error_message);
3601     guestfs_end_busy (g);
3602     return -1;
3603   }
3604
3605   guestfs_end_busy (g);
3606   return 0;
3607 }
3608
3609 struct vgcreate_ctx {
3610   /* This flag is set by the callbacks, so we know we've done
3611    * the callbacks as expected, and in the right sequence.
3612    * 0 = not called, 1 = reply_cb called.
3613    */
3614   int cb_sequence;
3615   struct guestfs_message_header hdr;
3616   struct guestfs_message_error err;
3617 };
3618
3619 static void vgcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3620 {
3621   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3622   struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data;
3623
3624   /* This should definitely not happen. */
3625   if (ctx->cb_sequence != 0) {
3626     ctx->cb_sequence = 9999;
3627     error (g, "%s: internal error: reply callback called twice", "guestfs_vgcreate");
3628     return;
3629   }
3630
3631   ml->main_loop_quit (ml, g);
3632
3633   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3634     error (g, "%s: failed to parse reply header", "guestfs_vgcreate");
3635     return;
3636   }
3637   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3638     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3639       error (g, "%s: failed to parse reply error", "guestfs_vgcreate");
3640       return;
3641     }
3642     goto done;
3643   }
3644  done:
3645   ctx->cb_sequence = 1;
3646 }
3647
3648 int guestfs_vgcreate (guestfs_h *g,
3649                 const char *volgroup,
3650                 char * const* const physvols)
3651 {
3652   struct guestfs_vgcreate_args args;
3653   struct vgcreate_ctx ctx;
3654   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3655   int serial;
3656
3657   if (check_state (g, "guestfs_vgcreate") == -1) return -1;
3658   guestfs_set_busy (g);
3659
3660   memset (&ctx, 0, sizeof ctx);
3661
3662   args.volgroup = (char *) volgroup;
3663   args.physvols.physvols_val = (char **) physvols;
3664   for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ;
3665   serial = guestfs__send_sync (g, GUESTFS_PROC_VGCREATE,
3666         (xdrproc_t) xdr_guestfs_vgcreate_args, (char *) &args);
3667   if (serial == -1) {
3668     guestfs_end_busy (g);
3669     return -1;
3670   }
3671
3672   guestfs__switch_to_receiving (g);
3673   ctx.cb_sequence = 0;
3674   guestfs_set_reply_callback (g, vgcreate_reply_cb, &ctx);
3675   (void) ml->main_loop_run (ml, g);
3676   guestfs_set_reply_callback (g, NULL, NULL);
3677   if (ctx.cb_sequence != 1) {
3678     error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate");
3679     guestfs_end_busy (g);
3680     return -1;
3681   }
3682
3683   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGCREATE, serial) == -1) {
3684     guestfs_end_busy (g);
3685     return -1;
3686   }
3687
3688   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3689     error (g, "%s", ctx.err.error_message);
3690     free (ctx.err.error_message);
3691     guestfs_end_busy (g);
3692     return -1;
3693   }
3694
3695   guestfs_end_busy (g);
3696   return 0;
3697 }
3698
3699 struct lvcreate_ctx {
3700   /* This flag is set by the callbacks, so we know we've done
3701    * the callbacks as expected, and in the right sequence.
3702    * 0 = not called, 1 = reply_cb called.
3703    */
3704   int cb_sequence;
3705   struct guestfs_message_header hdr;
3706   struct guestfs_message_error err;
3707 };
3708
3709 static void lvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3710 {
3711   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3712   struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data;
3713
3714   /* This should definitely not happen. */
3715   if (ctx->cb_sequence != 0) {
3716     ctx->cb_sequence = 9999;
3717     error (g, "%s: internal error: reply callback called twice", "guestfs_lvcreate");
3718     return;
3719   }
3720
3721   ml->main_loop_quit (ml, g);
3722
3723   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3724     error (g, "%s: failed to parse reply header", "guestfs_lvcreate");
3725     return;
3726   }
3727   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3728     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3729       error (g, "%s: failed to parse reply error", "guestfs_lvcreate");
3730       return;
3731     }
3732     goto done;
3733   }
3734  done:
3735   ctx->cb_sequence = 1;
3736 }
3737
3738 int guestfs_lvcreate (guestfs_h *g,
3739                 const char *logvol,
3740                 const char *volgroup,
3741                 int mbytes)
3742 {
3743   struct guestfs_lvcreate_args args;
3744   struct lvcreate_ctx ctx;
3745   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3746   int serial;
3747
3748   if (check_state (g, "guestfs_lvcreate") == -1) return -1;
3749   guestfs_set_busy (g);
3750
3751   memset (&ctx, 0, sizeof ctx);
3752
3753   args.logvol = (char *) logvol;
3754   args.volgroup = (char *) volgroup;
3755   args.mbytes = mbytes;
3756   serial = guestfs__send_sync (g, GUESTFS_PROC_LVCREATE,
3757         (xdrproc_t) xdr_guestfs_lvcreate_args, (char *) &args);
3758   if (serial == -1) {
3759     guestfs_end_busy (g);
3760     return -1;
3761   }
3762
3763   guestfs__switch_to_receiving (g);
3764   ctx.cb_sequence = 0;
3765   guestfs_set_reply_callback (g, lvcreate_reply_cb, &ctx);
3766   (void) ml->main_loop_run (ml, g);
3767   guestfs_set_reply_callback (g, NULL, NULL);
3768   if (ctx.cb_sequence != 1) {
3769     error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate");
3770     guestfs_end_busy (g);
3771     return -1;
3772   }
3773
3774   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVCREATE, serial) == -1) {
3775     guestfs_end_busy (g);
3776     return -1;
3777   }
3778
3779   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3780     error (g, "%s", ctx.err.error_message);
3781     free (ctx.err.error_message);
3782     guestfs_end_busy (g);
3783     return -1;
3784   }
3785
3786   guestfs_end_busy (g);
3787   return 0;
3788 }
3789
3790 struct mkfs_ctx {
3791   /* This flag is set by the callbacks, so we know we've done
3792    * the callbacks as expected, and in the right sequence.
3793    * 0 = not called, 1 = reply_cb called.
3794    */
3795   int cb_sequence;
3796   struct guestfs_message_header hdr;
3797   struct guestfs_message_error err;
3798 };
3799
3800 static void mkfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3801 {
3802   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3803   struct mkfs_ctx *ctx = (struct mkfs_ctx *) data;
3804
3805   /* This should definitely not happen. */
3806   if (ctx->cb_sequence != 0) {
3807     ctx->cb_sequence = 9999;
3808     error (g, "%s: internal error: reply callback called twice", "guestfs_mkfs");
3809     return;
3810   }
3811
3812   ml->main_loop_quit (ml, g);
3813
3814   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3815     error (g, "%s: failed to parse reply header", "guestfs_mkfs");
3816     return;
3817   }
3818   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3819     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3820       error (g, "%s: failed to parse reply error", "guestfs_mkfs");
3821       return;
3822     }
3823     goto done;
3824   }
3825  done:
3826   ctx->cb_sequence = 1;
3827 }
3828
3829 int guestfs_mkfs (guestfs_h *g,
3830                 const char *fstype,
3831                 const char *device)
3832 {
3833   struct guestfs_mkfs_args args;
3834   struct mkfs_ctx ctx;
3835   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3836   int serial;
3837
3838   if (check_state (g, "guestfs_mkfs") == -1) return -1;
3839   guestfs_set_busy (g);
3840
3841   memset (&ctx, 0, sizeof ctx);
3842
3843   args.fstype = (char *) fstype;
3844   args.device = (char *) device;
3845   serial = guestfs__send_sync (g, GUESTFS_PROC_MKFS,
3846         (xdrproc_t) xdr_guestfs_mkfs_args, (char *) &args);
3847   if (serial == -1) {
3848     guestfs_end_busy (g);
3849     return -1;
3850   }
3851
3852   guestfs__switch_to_receiving (g);
3853   ctx.cb_sequence = 0;
3854   guestfs_set_reply_callback (g, mkfs_reply_cb, &ctx);
3855   (void) ml->main_loop_run (ml, g);
3856   guestfs_set_reply_callback (g, NULL, NULL);
3857   if (ctx.cb_sequence != 1) {
3858     error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs");
3859     guestfs_end_busy (g);
3860     return -1;
3861   }
3862
3863   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFS, serial) == -1) {
3864     guestfs_end_busy (g);
3865     return -1;
3866   }
3867
3868   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3869     error (g, "%s", ctx.err.error_message);
3870     free (ctx.err.error_message);
3871     guestfs_end_busy (g);
3872     return -1;
3873   }
3874
3875   guestfs_end_busy (g);
3876   return 0;
3877 }
3878
3879 struct sfdisk_ctx {
3880   /* This flag is set by the callbacks, so we know we've done
3881    * the callbacks as expected, and in the right sequence.
3882    * 0 = not called, 1 = reply_cb called.
3883    */
3884   int cb_sequence;
3885   struct guestfs_message_header hdr;
3886   struct guestfs_message_error err;
3887 };
3888
3889 static void sfdisk_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3890 {
3891   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3892   struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data;
3893
3894   /* This should definitely not happen. */
3895   if (ctx->cb_sequence != 0) {
3896     ctx->cb_sequence = 9999;
3897     error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk");
3898     return;
3899   }
3900
3901   ml->main_loop_quit (ml, g);
3902
3903   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3904     error (g, "%s: failed to parse reply header", "guestfs_sfdisk");
3905     return;
3906   }
3907   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3908     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3909       error (g, "%s: failed to parse reply error", "guestfs_sfdisk");
3910       return;
3911     }
3912     goto done;
3913   }
3914  done:
3915   ctx->cb_sequence = 1;
3916 }
3917
3918 int guestfs_sfdisk (guestfs_h *g,
3919                 const char *device,
3920                 int cyls,
3921                 int heads,
3922                 int sectors,
3923                 char * const* const lines)
3924 {
3925   struct guestfs_sfdisk_args args;
3926   struct sfdisk_ctx ctx;
3927   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3928   int serial;
3929
3930   if (check_state (g, "guestfs_sfdisk") == -1) return -1;
3931   guestfs_set_busy (g);
3932
3933   memset (&ctx, 0, sizeof ctx);
3934
3935   args.device = (char *) device;
3936   args.cyls = cyls;
3937   args.heads = heads;
3938   args.sectors = sectors;
3939   args.lines.lines_val = (char **) lines;
3940   for (args.lines.lines_len = 0; lines[args.lines.lines_len]; args.lines.lines_len++) ;
3941   serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK,
3942         (xdrproc_t) xdr_guestfs_sfdisk_args, (char *) &args);
3943   if (serial == -1) {
3944     guestfs_end_busy (g);
3945     return -1;
3946   }
3947
3948   guestfs__switch_to_receiving (g);
3949   ctx.cb_sequence = 0;
3950   guestfs_set_reply_callback (g, sfdisk_reply_cb, &ctx);
3951   (void) ml->main_loop_run (ml, g);
3952   guestfs_set_reply_callback (g, NULL, NULL);
3953   if (ctx.cb_sequence != 1) {
3954     error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk");
3955     guestfs_end_busy (g);
3956     return -1;
3957   }
3958
3959   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK, serial) == -1) {
3960     guestfs_end_busy (g);
3961     return -1;
3962   }
3963
3964   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
3965     error (g, &qu