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