70d5ccec58160c37b4dd2abd815ceb2b8e546e11
[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 };
3980
3981 static void umount_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
3982 {
3983   guestfs_main_loop *ml = guestfs_get_main_loop (g);
3984   struct umount_all_ctx *ctx = (struct umount_all_ctx *) data;
3985
3986   ml->main_loop_quit (ml, g);
3987
3988   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
3989     error (g, "%s: failed to parse reply header", "guestfs_umount_all");
3990     return;
3991   }
3992   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
3993     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
3994       error (g, "%s: failed to parse reply error", "guestfs_umount_all");
3995       return;
3996     }
3997     goto done;
3998   }
3999  done:
4000   ctx->cb_sequence = 1001;
4001 }
4002
4003 int guestfs_umount_all (guestfs_h *g)
4004 {
4005   struct umount_all_ctx ctx;
4006   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4007   int serial;
4008
4009   if (check_state (g, "guestfs_umount_all") == -1) return -1;
4010   guestfs_set_busy (g);
4011
4012   memset (&ctx, 0, sizeof ctx);
4013
4014   serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
4015   if (serial == -1) {
4016     guestfs_set_ready (g);
4017     return -1;
4018   }
4019
4020  read_reply:
4021   guestfs__switch_to_receiving (g);
4022   ctx.cb_sequence = 0;
4023   guestfs_set_reply_callback (g, umount_all_reply_cb, &ctx);
4024   (void) ml->main_loop_run (ml, g);
4025   guestfs_set_reply_callback (g, NULL, NULL);
4026   if (ctx.cb_sequence != 1001) {
4027     error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all");
4028     guestfs_set_ready (g);
4029     return -1;
4030   }
4031
4032   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1) {
4033     guestfs_set_ready (g);
4034     return -1;
4035   }
4036
4037   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4038     error (g, "%s", ctx.err.error_message);
4039     guestfs_set_ready (g);
4040     return -1;
4041   }
4042
4043   guestfs_set_ready (g);
4044   return 0;
4045 }
4046
4047 struct lvm_remove_all_ctx {
4048   /* This flag is set by the callbacks, so we know we've done
4049    * the callbacks as expected, and in the right sequence.
4050    * 0 = not called, 1 = send called,
4051    * 1001 = reply called.
4052    */
4053   int cb_sequence;
4054   struct guestfs_message_header hdr;
4055   struct guestfs_message_error err;
4056 };
4057
4058 static void lvm_remove_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4059 {
4060   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4061   struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data;
4062
4063   ml->main_loop_quit (ml, g);
4064
4065   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4066     error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all");
4067     return;
4068   }
4069   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4070     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4071       error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all");
4072       return;
4073     }
4074     goto done;
4075   }
4076  done:
4077   ctx->cb_sequence = 1001;
4078 }
4079
4080 int guestfs_lvm_remove_all (guestfs_h *g)
4081 {
4082   struct lvm_remove_all_ctx ctx;
4083   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4084   int serial;
4085
4086   if (check_state (g, "guestfs_lvm_remove_all") == -1) return -1;
4087   guestfs_set_busy (g);
4088
4089   memset (&ctx, 0, sizeof ctx);
4090
4091   serial = guestfs__send_sync (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
4092   if (serial == -1) {
4093     guestfs_set_ready (g);
4094     return -1;
4095   }
4096
4097  read_reply:
4098   guestfs__switch_to_receiving (g);
4099   ctx.cb_sequence = 0;
4100   guestfs_set_reply_callback (g, lvm_remove_all_reply_cb, &ctx);
4101   (void) ml->main_loop_run (ml, g);
4102   guestfs_set_reply_callback (g, NULL, NULL);
4103   if (ctx.cb_sequence != 1001) {
4104     error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all");
4105     guestfs_set_ready (g);
4106     return -1;
4107   }
4108
4109   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1) {
4110     guestfs_set_ready (g);
4111     return -1;
4112   }
4113
4114   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4115     error (g, "%s", ctx.err.error_message);
4116     guestfs_set_ready (g);
4117     return -1;
4118   }
4119
4120   guestfs_set_ready (g);
4121   return 0;
4122 }
4123
4124 struct file_ctx {
4125   /* This flag is set by the callbacks, so we know we've done
4126    * the callbacks as expected, and in the right sequence.
4127    * 0 = not called, 1 = send called,
4128    * 1001 = reply called.
4129    */
4130   int cb_sequence;
4131   struct guestfs_message_header hdr;
4132   struct guestfs_message_error err;
4133   struct guestfs_file_ret ret;
4134 };
4135
4136 static void file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4137 {
4138   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4139   struct file_ctx *ctx = (struct file_ctx *) data;
4140
4141   ml->main_loop_quit (ml, g);
4142
4143   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4144     error (g, "%s: failed to parse reply header", "guestfs_file");
4145     return;
4146   }
4147   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4148     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4149       error (g, "%s: failed to parse reply error", "guestfs_file");
4150       return;
4151     }
4152     goto done;
4153   }
4154   if (!xdr_guestfs_file_ret (xdr, &ctx->ret)) {
4155     error (g, "%s: failed to parse reply", "guestfs_file");
4156     return;
4157   }
4158  done:
4159   ctx->cb_sequence = 1001;
4160 }
4161
4162 char *guestfs_file (guestfs_h *g,
4163                 const char *path)
4164 {
4165   struct guestfs_file_args args;
4166   struct file_ctx ctx;
4167   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4168   int serial;
4169
4170   if (check_state (g, "guestfs_file") == -1) return NULL;
4171   guestfs_set_busy (g);
4172
4173   memset (&ctx, 0, sizeof ctx);
4174
4175   args.path = (char *) path;
4176   serial = guestfs__send_sync (g, GUESTFS_PROC_FILE,
4177         (xdrproc_t) xdr_guestfs_file_args, (char *) &args);
4178   if (serial == -1) {
4179     guestfs_set_ready (g);
4180     return NULL;
4181   }
4182
4183  read_reply:
4184   guestfs__switch_to_receiving (g);
4185   ctx.cb_sequence = 0;
4186   guestfs_set_reply_callback (g, file_reply_cb, &ctx);
4187   (void) ml->main_loop_run (ml, g);
4188   guestfs_set_reply_callback (g, NULL, NULL);
4189   if (ctx.cb_sequence != 1001) {
4190     error (g, "%s reply failed, see earlier error messages", "guestfs_file");
4191     guestfs_set_ready (g);
4192     return NULL;
4193   }
4194
4195   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FILE, serial) == -1) {
4196     guestfs_set_ready (g);
4197     return NULL;
4198   }
4199
4200   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4201     error (g, "%s", ctx.err.error_message);
4202     guestfs_set_ready (g);
4203     return NULL;
4204   }
4205
4206   guestfs_set_ready (g);
4207   return ctx.ret.description; /* caller will free */
4208 }
4209
4210 struct command_ctx {
4211   /* This flag is set by the callbacks, so we know we've done
4212    * the callbacks as expected, and in the right sequence.
4213    * 0 = not called, 1 = send called,
4214    * 1001 = reply called.
4215    */
4216   int cb_sequence;
4217   struct guestfs_message_header hdr;
4218   struct guestfs_message_error err;
4219   struct guestfs_command_ret ret;
4220 };
4221
4222 static void command_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4223 {
4224   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4225   struct command_ctx *ctx = (struct command_ctx *) data;
4226
4227   ml->main_loop_quit (ml, g);
4228
4229   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4230     error (g, "%s: failed to parse reply header", "guestfs_command");
4231     return;
4232   }
4233   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4234     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4235       error (g, "%s: failed to parse reply error", "guestfs_command");
4236       return;
4237     }
4238     goto done;
4239   }
4240   if (!xdr_guestfs_command_ret (xdr, &ctx->ret)) {
4241     error (g, "%s: failed to parse reply", "guestfs_command");
4242     return;
4243   }
4244  done:
4245   ctx->cb_sequence = 1001;
4246 }
4247
4248 char *guestfs_command (guestfs_h *g,
4249                 char * const* const arguments)
4250 {
4251   struct guestfs_command_args args;
4252   struct command_ctx ctx;
4253   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4254   int serial;
4255
4256   if (check_state (g, "guestfs_command") == -1) return NULL;
4257   guestfs_set_busy (g);
4258
4259   memset (&ctx, 0, sizeof ctx);
4260
4261   args.arguments.arguments_val = (char **) arguments;
4262   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4263   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND,
4264         (xdrproc_t) xdr_guestfs_command_args, (char *) &args);
4265   if (serial == -1) {
4266     guestfs_set_ready (g);
4267     return NULL;
4268   }
4269
4270  read_reply:
4271   guestfs__switch_to_receiving (g);
4272   ctx.cb_sequence = 0;
4273   guestfs_set_reply_callback (g, command_reply_cb, &ctx);
4274   (void) ml->main_loop_run (ml, g);
4275   guestfs_set_reply_callback (g, NULL, NULL);
4276   if (ctx.cb_sequence != 1001) {
4277     error (g, "%s reply failed, see earlier error messages", "guestfs_command");
4278     guestfs_set_ready (g);
4279     return NULL;
4280   }
4281
4282   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND, serial) == -1) {
4283     guestfs_set_ready (g);
4284     return NULL;
4285   }
4286
4287   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4288     error (g, "%s", ctx.err.error_message);
4289     guestfs_set_ready (g);
4290     return NULL;
4291   }
4292
4293   guestfs_set_ready (g);
4294   return ctx.ret.output; /* caller will free */
4295 }
4296
4297 struct command_lines_ctx {
4298   /* This flag is set by the callbacks, so we know we've done
4299    * the callbacks as expected, and in the right sequence.
4300    * 0 = not called, 1 = send called,
4301    * 1001 = reply called.
4302    */
4303   int cb_sequence;
4304   struct guestfs_message_header hdr;
4305   struct guestfs_message_error err;
4306   struct guestfs_command_lines_ret ret;
4307 };
4308
4309 static void command_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4310 {
4311   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4312   struct command_lines_ctx *ctx = (struct command_lines_ctx *) data;
4313
4314   ml->main_loop_quit (ml, g);
4315
4316   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4317     error (g, "%s: failed to parse reply header", "guestfs_command_lines");
4318     return;
4319   }
4320   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4321     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4322       error (g, "%s: failed to parse reply error", "guestfs_command_lines");
4323       return;
4324     }
4325     goto done;
4326   }
4327   if (!xdr_guestfs_command_lines_ret (xdr, &ctx->ret)) {
4328     error (g, "%s: failed to parse reply", "guestfs_command_lines");
4329     return;
4330   }
4331  done:
4332   ctx->cb_sequence = 1001;
4333 }
4334
4335 char **guestfs_command_lines (guestfs_h *g,
4336                 char * const* const arguments)
4337 {
4338   struct guestfs_command_lines_args args;
4339   struct command_lines_ctx ctx;
4340   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4341   int serial;
4342
4343   if (check_state (g, "guestfs_command_lines") == -1) return NULL;
4344   guestfs_set_busy (g);
4345
4346   memset (&ctx, 0, sizeof ctx);
4347
4348   args.arguments.arguments_val = (char **) arguments;
4349   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
4350   serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND_LINES,
4351         (xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args);
4352   if (serial == -1) {
4353     guestfs_set_ready (g);
4354     return NULL;
4355   }
4356
4357  read_reply:
4358   guestfs__switch_to_receiving (g);
4359   ctx.cb_sequence = 0;
4360   guestfs_set_reply_callback (g, command_lines_reply_cb, &ctx);
4361   (void) ml->main_loop_run (ml, g);
4362   guestfs_set_reply_callback (g, NULL, NULL);
4363   if (ctx.cb_sequence != 1001) {
4364     error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines");
4365     guestfs_set_ready (g);
4366     return NULL;
4367   }
4368
4369   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1) {
4370     guestfs_set_ready (g);
4371     return NULL;
4372   }
4373
4374   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4375     error (g, "%s", ctx.err.error_message);
4376     guestfs_set_ready (g);
4377     return NULL;
4378   }
4379
4380   guestfs_set_ready (g);
4381   /* caller will free this, but we need to add a NULL entry */
4382   ctx.ret.lines.lines_val =
4383     safe_realloc (g, ctx.ret.lines.lines_val,
4384                   sizeof (char *) * (ctx.ret.lines.lines_len + 1));
4385   ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
4386   return ctx.ret.lines.lines_val;
4387 }
4388
4389 struct stat_ctx {
4390   /* This flag is set by the callbacks, so we know we've done
4391    * the callbacks as expected, and in the right sequence.
4392    * 0 = not called, 1 = send called,
4393    * 1001 = reply called.
4394    */
4395   int cb_sequence;
4396   struct guestfs_message_header hdr;
4397   struct guestfs_message_error err;
4398   struct guestfs_stat_ret ret;
4399 };
4400
4401 static void stat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4402 {
4403   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4404   struct stat_ctx *ctx = (struct stat_ctx *) data;
4405
4406   ml->main_loop_quit (ml, g);
4407
4408   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4409     error (g, "%s: failed to parse reply header", "guestfs_stat");
4410     return;
4411   }
4412   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4413     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4414       error (g, "%s: failed to parse reply error", "guestfs_stat");
4415       return;
4416     }
4417     goto done;
4418   }
4419   if (!xdr_guestfs_stat_ret (xdr, &ctx->ret)) {
4420     error (g, "%s: failed to parse reply", "guestfs_stat");
4421     return;
4422   }
4423  done:
4424   ctx->cb_sequence = 1001;
4425 }
4426
4427 struct guestfs_stat *guestfs_stat (guestfs_h *g,
4428                 const char *path)
4429 {
4430   struct guestfs_stat_args args;
4431   struct stat_ctx ctx;
4432   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4433   int serial;
4434
4435   if (check_state (g, "guestfs_stat") == -1) return NULL;
4436   guestfs_set_busy (g);
4437
4438   memset (&ctx, 0, sizeof ctx);
4439
4440   args.path = (char *) path;
4441   serial = guestfs__send_sync (g, GUESTFS_PROC_STAT,
4442         (xdrproc_t) xdr_guestfs_stat_args, (char *) &args);
4443   if (serial == -1) {
4444     guestfs_set_ready (g);
4445     return NULL;
4446   }
4447
4448  read_reply:
4449   guestfs__switch_to_receiving (g);
4450   ctx.cb_sequence = 0;
4451   guestfs_set_reply_callback (g, stat_reply_cb, &ctx);
4452   (void) ml->main_loop_run (ml, g);
4453   guestfs_set_reply_callback (g, NULL, NULL);
4454   if (ctx.cb_sequence != 1001) {
4455     error (g, "%s reply failed, see earlier error messages", "guestfs_stat");
4456     guestfs_set_ready (g);
4457     return NULL;
4458   }
4459
4460   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STAT, serial) == -1) {
4461     guestfs_set_ready (g);
4462     return NULL;
4463   }
4464
4465   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4466     error (g, "%s", ctx.err.error_message);
4467     guestfs_set_ready (g);
4468     return NULL;
4469   }
4470
4471   guestfs_set_ready (g);
4472   /* caller will free this */
4473   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4474 }
4475
4476 struct lstat_ctx {
4477   /* This flag is set by the callbacks, so we know we've done
4478    * the callbacks as expected, and in the right sequence.
4479    * 0 = not called, 1 = send called,
4480    * 1001 = reply called.
4481    */
4482   int cb_sequence;
4483   struct guestfs_message_header hdr;
4484   struct guestfs_message_error err;
4485   struct guestfs_lstat_ret ret;
4486 };
4487
4488 static void lstat_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4489 {
4490   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4491   struct lstat_ctx *ctx = (struct lstat_ctx *) data;
4492
4493   ml->main_loop_quit (ml, g);
4494
4495   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4496     error (g, "%s: failed to parse reply header", "guestfs_lstat");
4497     return;
4498   }
4499   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4500     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4501       error (g, "%s: failed to parse reply error", "guestfs_lstat");
4502       return;
4503     }
4504     goto done;
4505   }
4506   if (!xdr_guestfs_lstat_ret (xdr, &ctx->ret)) {
4507     error (g, "%s: failed to parse reply", "guestfs_lstat");
4508     return;
4509   }
4510  done:
4511   ctx->cb_sequence = 1001;
4512 }
4513
4514 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
4515                 const char *path)
4516 {
4517   struct guestfs_lstat_args args;
4518   struct lstat_ctx ctx;
4519   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4520   int serial;
4521
4522   if (check_state (g, "guestfs_lstat") == -1) return NULL;
4523   guestfs_set_busy (g);
4524
4525   memset (&ctx, 0, sizeof ctx);
4526
4527   args.path = (char *) path;
4528   serial = guestfs__send_sync (g, GUESTFS_PROC_LSTAT,
4529         (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args);
4530   if (serial == -1) {
4531     guestfs_set_ready (g);
4532     return NULL;
4533   }
4534
4535  read_reply:
4536   guestfs__switch_to_receiving (g);
4537   ctx.cb_sequence = 0;
4538   guestfs_set_reply_callback (g, lstat_reply_cb, &ctx);
4539   (void) ml->main_loop_run (ml, g);
4540   guestfs_set_reply_callback (g, NULL, NULL);
4541   if (ctx.cb_sequence != 1001) {
4542     error (g, "%s reply failed, see earlier error messages", "guestfs_lstat");
4543     guestfs_set_ready (g);
4544     return NULL;
4545   }
4546
4547   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LSTAT, serial) == -1) {
4548     guestfs_set_ready (g);
4549     return NULL;
4550   }
4551
4552   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4553     error (g, "%s", ctx.err.error_message);
4554     guestfs_set_ready (g);
4555     return NULL;
4556   }
4557
4558   guestfs_set_ready (g);
4559   /* caller will free this */
4560   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4561 }
4562
4563 struct statvfs_ctx {
4564   /* This flag is set by the callbacks, so we know we've done
4565    * the callbacks as expected, and in the right sequence.
4566    * 0 = not called, 1 = send called,
4567    * 1001 = reply called.
4568    */
4569   int cb_sequence;
4570   struct guestfs_message_header hdr;
4571   struct guestfs_message_error err;
4572   struct guestfs_statvfs_ret ret;
4573 };
4574
4575 static void statvfs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4576 {
4577   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4578   struct statvfs_ctx *ctx = (struct statvfs_ctx *) data;
4579
4580   ml->main_loop_quit (ml, g);
4581
4582   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4583     error (g, "%s: failed to parse reply header", "guestfs_statvfs");
4584     return;
4585   }
4586   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4587     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4588       error (g, "%s: failed to parse reply error", "guestfs_statvfs");
4589       return;
4590     }
4591     goto done;
4592   }
4593   if (!xdr_guestfs_statvfs_ret (xdr, &ctx->ret)) {
4594     error (g, "%s: failed to parse reply", "guestfs_statvfs");
4595     return;
4596   }
4597  done:
4598   ctx->cb_sequence = 1001;
4599 }
4600
4601 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
4602                 const char *path)
4603 {
4604   struct guestfs_statvfs_args args;
4605   struct statvfs_ctx ctx;
4606   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4607   int serial;
4608
4609   if (check_state (g, "guestfs_statvfs") == -1) return NULL;
4610   guestfs_set_busy (g);
4611
4612   memset (&ctx, 0, sizeof ctx);
4613
4614   args.path = (char *) path;
4615   serial = guestfs__send_sync (g, GUESTFS_PROC_STATVFS,
4616         (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args);
4617   if (serial == -1) {
4618     guestfs_set_ready (g);
4619     return NULL;
4620   }
4621
4622  read_reply:
4623   guestfs__switch_to_receiving (g);
4624   ctx.cb_sequence = 0;
4625   guestfs_set_reply_callback (g, statvfs_reply_cb, &ctx);
4626   (void) ml->main_loop_run (ml, g);
4627   guestfs_set_reply_callback (g, NULL, NULL);
4628   if (ctx.cb_sequence != 1001) {
4629     error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs");
4630     guestfs_set_ready (g);
4631     return NULL;
4632   }
4633
4634   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STATVFS, serial) == -1) {
4635     guestfs_set_ready (g);
4636     return NULL;
4637   }
4638
4639   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4640     error (g, "%s", ctx.err.error_message);
4641     guestfs_set_ready (g);
4642     return NULL;
4643   }
4644
4645   guestfs_set_ready (g);
4646   /* caller will free this */
4647   return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf));
4648 }
4649
4650 struct tune2fs_l_ctx {
4651   /* This flag is set by the callbacks, so we know we've done
4652    * the callbacks as expected, and in the right sequence.
4653    * 0 = not called, 1 = send called,
4654    * 1001 = reply called.
4655    */
4656   int cb_sequence;
4657   struct guestfs_message_header hdr;
4658   struct guestfs_message_error err;
4659   struct guestfs_tune2fs_l_ret ret;
4660 };
4661
4662 static void tune2fs_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4663 {
4664   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4665   struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data;
4666
4667   ml->main_loop_quit (ml, g);
4668
4669   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4670     error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l");
4671     return;
4672   }
4673   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4674     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4675       error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l");
4676       return;
4677     }
4678     goto done;
4679   }
4680   if (!xdr_guestfs_tune2fs_l_ret (xdr, &ctx->ret)) {
4681     error (g, "%s: failed to parse reply", "guestfs_tune2fs_l");
4682     return;
4683   }
4684  done:
4685   ctx->cb_sequence = 1001;
4686 }
4687
4688 char **guestfs_tune2fs_l (guestfs_h *g,
4689                 const char *device)
4690 {
4691   struct guestfs_tune2fs_l_args args;
4692   struct tune2fs_l_ctx ctx;
4693   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4694   int serial;
4695
4696   if (check_state (g, "guestfs_tune2fs_l") == -1) return NULL;
4697   guestfs_set_busy (g);
4698
4699   memset (&ctx, 0, sizeof ctx);
4700
4701   args.device = (char *) device;
4702   serial = guestfs__send_sync (g, GUESTFS_PROC_TUNE2FS_L,
4703         (xdrproc_t) xdr_guestfs_tune2fs_l_args, (char *) &args);
4704   if (serial == -1) {
4705     guestfs_set_ready (g);
4706     return NULL;
4707   }
4708
4709  read_reply:
4710   guestfs__switch_to_receiving (g);
4711   ctx.cb_sequence = 0;
4712   guestfs_set_reply_callback (g, tune2fs_l_reply_cb, &ctx);
4713   (void) ml->main_loop_run (ml, g);
4714   guestfs_set_reply_callback (g, NULL, NULL);
4715   if (ctx.cb_sequence != 1001) {
4716     error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l");
4717     guestfs_set_ready (g);
4718     return NULL;
4719   }
4720
4721   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1) {
4722     guestfs_set_ready (g);
4723     return NULL;
4724   }
4725
4726   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4727     error (g, "%s", ctx.err.error_message);
4728     guestfs_set_ready (g);
4729     return NULL;
4730   }
4731
4732   guestfs_set_ready (g);
4733   /* caller will free this, but we need to add a NULL entry */
4734   ctx.ret.superblock.superblock_val =
4735     safe_realloc (g, ctx.ret.superblock.superblock_val,
4736                   sizeof (char *) * (ctx.ret.superblock.superblock_len + 1));
4737   ctx.ret.superblock.superblock_val[ctx.ret.superblock.superblock_len] = NULL;
4738   return ctx.ret.superblock.superblock_val;
4739 }
4740
4741 struct blockdev_setro_ctx {
4742   /* This flag is set by the callbacks, so we know we've done
4743    * the callbacks as expected, and in the right sequence.
4744    * 0 = not called, 1 = send called,
4745    * 1001 = reply called.
4746    */
4747   int cb_sequence;
4748   struct guestfs_message_header hdr;
4749   struct guestfs_message_error err;
4750 };
4751
4752 static void blockdev_setro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4753 {
4754   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4755   struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data;
4756
4757   ml->main_loop_quit (ml, g);
4758
4759   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4760     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro");
4761     return;
4762   }
4763   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4764     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4765       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro");
4766       return;
4767     }
4768     goto done;
4769   }
4770  done:
4771   ctx->cb_sequence = 1001;
4772 }
4773
4774 int guestfs_blockdev_setro (guestfs_h *g,
4775                 const char *device)
4776 {
4777   struct guestfs_blockdev_setro_args args;
4778   struct blockdev_setro_ctx ctx;
4779   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4780   int serial;
4781
4782   if (check_state (g, "guestfs_blockdev_setro") == -1) return -1;
4783   guestfs_set_busy (g);
4784
4785   memset (&ctx, 0, sizeof ctx);
4786
4787   args.device = (char *) device;
4788   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRO,
4789         (xdrproc_t) xdr_guestfs_blockdev_setro_args, (char *) &args);
4790   if (serial == -1) {
4791     guestfs_set_ready (g);
4792     return -1;
4793   }
4794
4795  read_reply:
4796   guestfs__switch_to_receiving (g);
4797   ctx.cb_sequence = 0;
4798   guestfs_set_reply_callback (g, blockdev_setro_reply_cb, &ctx);
4799   (void) ml->main_loop_run (ml, g);
4800   guestfs_set_reply_callback (g, NULL, NULL);
4801   if (ctx.cb_sequence != 1001) {
4802     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro");
4803     guestfs_set_ready (g);
4804     return -1;
4805   }
4806
4807   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1) {
4808     guestfs_set_ready (g);
4809     return -1;
4810   }
4811
4812   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4813     error (g, "%s", ctx.err.error_message);
4814     guestfs_set_ready (g);
4815     return -1;
4816   }
4817
4818   guestfs_set_ready (g);
4819   return 0;
4820 }
4821
4822 struct blockdev_setrw_ctx {
4823   /* This flag is set by the callbacks, so we know we've done
4824    * the callbacks as expected, and in the right sequence.
4825    * 0 = not called, 1 = send called,
4826    * 1001 = reply called.
4827    */
4828   int cb_sequence;
4829   struct guestfs_message_header hdr;
4830   struct guestfs_message_error err;
4831 };
4832
4833 static void blockdev_setrw_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4834 {
4835   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4836   struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data;
4837
4838   ml->main_loop_quit (ml, g);
4839
4840   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4841     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw");
4842     return;
4843   }
4844   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4845     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4846       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw");
4847       return;
4848     }
4849     goto done;
4850   }
4851  done:
4852   ctx->cb_sequence = 1001;
4853 }
4854
4855 int guestfs_blockdev_setrw (guestfs_h *g,
4856                 const char *device)
4857 {
4858   struct guestfs_blockdev_setrw_args args;
4859   struct blockdev_setrw_ctx ctx;
4860   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4861   int serial;
4862
4863   if (check_state (g, "guestfs_blockdev_setrw") == -1) return -1;
4864   guestfs_set_busy (g);
4865
4866   memset (&ctx, 0, sizeof ctx);
4867
4868   args.device = (char *) device;
4869   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRW,
4870         (xdrproc_t) xdr_guestfs_blockdev_setrw_args, (char *) &args);
4871   if (serial == -1) {
4872     guestfs_set_ready (g);
4873     return -1;
4874   }
4875
4876  read_reply:
4877   guestfs__switch_to_receiving (g);
4878   ctx.cb_sequence = 0;
4879   guestfs_set_reply_callback (g, blockdev_setrw_reply_cb, &ctx);
4880   (void) ml->main_loop_run (ml, g);
4881   guestfs_set_reply_callback (g, NULL, NULL);
4882   if (ctx.cb_sequence != 1001) {
4883     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw");
4884     guestfs_set_ready (g);
4885     return -1;
4886   }
4887
4888   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1) {
4889     guestfs_set_ready (g);
4890     return -1;
4891   }
4892
4893   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4894     error (g, "%s", ctx.err.error_message);
4895     guestfs_set_ready (g);
4896     return -1;
4897   }
4898
4899   guestfs_set_ready (g);
4900   return 0;
4901 }
4902
4903 struct blockdev_getro_ctx {
4904   /* This flag is set by the callbacks, so we know we've done
4905    * the callbacks as expected, and in the right sequence.
4906    * 0 = not called, 1 = send called,
4907    * 1001 = reply called.
4908    */
4909   int cb_sequence;
4910   struct guestfs_message_header hdr;
4911   struct guestfs_message_error err;
4912   struct guestfs_blockdev_getro_ret ret;
4913 };
4914
4915 static void blockdev_getro_reply_cb (guestfs_h *g, void *data, XDR *xdr)
4916 {
4917   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4918   struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data;
4919
4920   ml->main_loop_quit (ml, g);
4921
4922   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
4923     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro");
4924     return;
4925   }
4926   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
4927     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
4928       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro");
4929       return;
4930     }
4931     goto done;
4932   }
4933   if (!xdr_guestfs_blockdev_getro_ret (xdr, &ctx->ret)) {
4934     error (g, "%s: failed to parse reply", "guestfs_blockdev_getro");
4935     return;
4936   }
4937  done:
4938   ctx->cb_sequence = 1001;
4939 }
4940
4941 int guestfs_blockdev_getro (guestfs_h *g,
4942                 const char *device)
4943 {
4944   struct guestfs_blockdev_getro_args args;
4945   struct blockdev_getro_ctx ctx;
4946   guestfs_main_loop *ml = guestfs_get_main_loop (g);
4947   int serial;
4948
4949   if (check_state (g, "guestfs_blockdev_getro") == -1) return -1;
4950   guestfs_set_busy (g);
4951
4952   memset (&ctx, 0, sizeof ctx);
4953
4954   args.device = (char *) device;
4955   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETRO,
4956         (xdrproc_t) xdr_guestfs_blockdev_getro_args, (char *) &args);
4957   if (serial == -1) {
4958     guestfs_set_ready (g);
4959     return -1;
4960   }
4961
4962  read_reply:
4963   guestfs__switch_to_receiving (g);
4964   ctx.cb_sequence = 0;
4965   guestfs_set_reply_callback (g, blockdev_getro_reply_cb, &ctx);
4966   (void) ml->main_loop_run (ml, g);
4967   guestfs_set_reply_callback (g, NULL, NULL);
4968   if (ctx.cb_sequence != 1001) {
4969     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro");
4970     guestfs_set_ready (g);
4971     return -1;
4972   }
4973
4974   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1) {
4975     guestfs_set_ready (g);
4976     return -1;
4977   }
4978
4979   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
4980     error (g, "%s", ctx.err.error_message);
4981     guestfs_set_ready (g);
4982     return -1;
4983   }
4984
4985   guestfs_set_ready (g);
4986   return ctx.ret.ro;
4987 }
4988
4989 struct blockdev_getss_ctx {
4990   /* This flag is set by the callbacks, so we know we've done
4991    * the callbacks as expected, and in the right sequence.
4992    * 0 = not called, 1 = send called,
4993    * 1001 = reply called.
4994    */
4995   int cb_sequence;
4996   struct guestfs_message_header hdr;
4997   struct guestfs_message_error err;
4998   struct guestfs_blockdev_getss_ret ret;
4999 };
5000
5001 static void blockdev_getss_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5002 {
5003   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5004   struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data;
5005
5006   ml->main_loop_quit (ml, g);
5007
5008   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5009     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss");
5010     return;
5011   }
5012   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5013     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5014       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss");
5015       return;
5016     }
5017     goto done;
5018   }
5019   if (!xdr_guestfs_blockdev_getss_ret (xdr, &ctx->ret)) {
5020     error (g, "%s: failed to parse reply", "guestfs_blockdev_getss");
5021     return;
5022   }
5023  done:
5024   ctx->cb_sequence = 1001;
5025 }
5026
5027 int guestfs_blockdev_getss (guestfs_h *g,
5028                 const char *device)
5029 {
5030   struct guestfs_blockdev_getss_args args;
5031   struct blockdev_getss_ctx ctx;
5032   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5033   int serial;
5034
5035   if (check_state (g, "guestfs_blockdev_getss") == -1) return -1;
5036   guestfs_set_busy (g);
5037
5038   memset (&ctx, 0, sizeof ctx);
5039
5040   args.device = (char *) device;
5041   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSS,
5042         (xdrproc_t) xdr_guestfs_blockdev_getss_args, (char *) &args);
5043   if (serial == -1) {
5044     guestfs_set_ready (g);
5045     return -1;
5046   }
5047
5048  read_reply:
5049   guestfs__switch_to_receiving (g);
5050   ctx.cb_sequence = 0;
5051   guestfs_set_reply_callback (g, blockdev_getss_reply_cb, &ctx);
5052   (void) ml->main_loop_run (ml, g);
5053   guestfs_set_reply_callback (g, NULL, NULL);
5054   if (ctx.cb_sequence != 1001) {
5055     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss");
5056     guestfs_set_ready (g);
5057     return -1;
5058   }
5059
5060   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1) {
5061     guestfs_set_ready (g);
5062     return -1;
5063   }
5064
5065   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5066     error (g, "%s", ctx.err.error_message);
5067     guestfs_set_ready (g);
5068     return -1;
5069   }
5070
5071   guestfs_set_ready (g);
5072   return ctx.ret.sectorsize;
5073 }
5074
5075 struct blockdev_getbsz_ctx {
5076   /* This flag is set by the callbacks, so we know we've done
5077    * the callbacks as expected, and in the right sequence.
5078    * 0 = not called, 1 = send called,
5079    * 1001 = reply called.
5080    */
5081   int cb_sequence;
5082   struct guestfs_message_header hdr;
5083   struct guestfs_message_error err;
5084   struct guestfs_blockdev_getbsz_ret ret;
5085 };
5086
5087 static void blockdev_getbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5088 {
5089   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5090   struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data;
5091
5092   ml->main_loop_quit (ml, g);
5093
5094   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5095     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz");
5096     return;
5097   }
5098   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5099     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5100       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz");
5101       return;
5102     }
5103     goto done;
5104   }
5105   if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &ctx->ret)) {
5106     error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz");
5107     return;
5108   }
5109  done:
5110   ctx->cb_sequence = 1001;
5111 }
5112
5113 int guestfs_blockdev_getbsz (guestfs_h *g,
5114                 const char *device)
5115 {
5116   struct guestfs_blockdev_getbsz_args args;
5117   struct blockdev_getbsz_ctx ctx;
5118   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5119   int serial;
5120
5121   if (check_state (g, "guestfs_blockdev_getbsz") == -1) return -1;
5122   guestfs_set_busy (g);
5123
5124   memset (&ctx, 0, sizeof ctx);
5125
5126   args.device = (char *) device;
5127   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
5128         (xdrproc_t) xdr_guestfs_blockdev_getbsz_args, (char *) &args);
5129   if (serial == -1) {
5130     guestfs_set_ready (g);
5131     return -1;
5132   }
5133
5134  read_reply:
5135   guestfs__switch_to_receiving (g);
5136   ctx.cb_sequence = 0;
5137   guestfs_set_reply_callback (g, blockdev_getbsz_reply_cb, &ctx);
5138   (void) ml->main_loop_run (ml, g);
5139   guestfs_set_reply_callback (g, NULL, NULL);
5140   if (ctx.cb_sequence != 1001) {
5141     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz");
5142     guestfs_set_ready (g);
5143     return -1;
5144   }
5145
5146   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1) {
5147     guestfs_set_ready (g);
5148     return -1;
5149   }
5150
5151   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5152     error (g, "%s", ctx.err.error_message);
5153     guestfs_set_ready (g);
5154     return -1;
5155   }
5156
5157   guestfs_set_ready (g);
5158   return ctx.ret.blocksize;
5159 }
5160
5161 struct blockdev_setbsz_ctx {
5162   /* This flag is set by the callbacks, so we know we've done
5163    * the callbacks as expected, and in the right sequence.
5164    * 0 = not called, 1 = send called,
5165    * 1001 = reply called.
5166    */
5167   int cb_sequence;
5168   struct guestfs_message_header hdr;
5169   struct guestfs_message_error err;
5170 };
5171
5172 static void blockdev_setbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5173 {
5174   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5175   struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data;
5176
5177   ml->main_loop_quit (ml, g);
5178
5179   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5180     error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz");
5181     return;
5182   }
5183   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5184     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5185       error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz");
5186       return;
5187     }
5188     goto done;
5189   }
5190  done:
5191   ctx->cb_sequence = 1001;
5192 }
5193
5194 int guestfs_blockdev_setbsz (guestfs_h *g,
5195                 const char *device,
5196                 int blocksize)
5197 {
5198   struct guestfs_blockdev_setbsz_args args;
5199   struct blockdev_setbsz_ctx ctx;
5200   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5201   int serial;
5202
5203   if (check_state (g, "guestfs_blockdev_setbsz") == -1) return -1;
5204   guestfs_set_busy (g);
5205
5206   memset (&ctx, 0, sizeof ctx);
5207
5208   args.device = (char *) device;
5209   args.blocksize = blocksize;
5210   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETBSZ,
5211         (xdrproc_t) xdr_guestfs_blockdev_setbsz_args, (char *) &args);
5212   if (serial == -1) {
5213     guestfs_set_ready (g);
5214     return -1;
5215   }
5216
5217  read_reply:
5218   guestfs__switch_to_receiving (g);
5219   ctx.cb_sequence = 0;
5220   guestfs_set_reply_callback (g, blockdev_setbsz_reply_cb, &ctx);
5221   (void) ml->main_loop_run (ml, g);
5222   guestfs_set_reply_callback (g, NULL, NULL);
5223   if (ctx.cb_sequence != 1001) {
5224     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz");
5225     guestfs_set_ready (g);
5226     return -1;
5227   }
5228
5229   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1) {
5230     guestfs_set_ready (g);
5231     return -1;
5232   }
5233
5234   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5235     error (g, "%s", ctx.err.error_message);
5236     guestfs_set_ready (g);
5237     return -1;
5238   }
5239
5240   guestfs_set_ready (g);
5241   return 0;
5242 }
5243
5244 struct blockdev_getsz_ctx {
5245   /* This flag is set by the callbacks, so we know we've done
5246    * the callbacks as expected, and in the right sequence.
5247    * 0 = not called, 1 = send called,
5248    * 1001 = reply called.
5249    */
5250   int cb_sequence;
5251   struct guestfs_message_header hdr;
5252   struct guestfs_message_error err;
5253   struct guestfs_blockdev_getsz_ret ret;
5254 };
5255
5256 static void blockdev_getsz_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5257 {
5258   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5259   struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data;
5260
5261   ml->main_loop_quit (ml, g);
5262
5263   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5264     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz");
5265     return;
5266   }
5267   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5268     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5269       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz");
5270       return;
5271     }
5272     goto done;
5273   }
5274   if (!xdr_guestfs_blockdev_getsz_ret (xdr, &ctx->ret)) {
5275     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz");
5276     return;
5277   }
5278  done:
5279   ctx->cb_sequence = 1001;
5280 }
5281
5282 int64_t guestfs_blockdev_getsz (guestfs_h *g,
5283                 const char *device)
5284 {
5285   struct guestfs_blockdev_getsz_args args;
5286   struct blockdev_getsz_ctx ctx;
5287   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5288   int serial;
5289
5290   if (check_state (g, "guestfs_blockdev_getsz") == -1) return -1;
5291   guestfs_set_busy (g);
5292
5293   memset (&ctx, 0, sizeof ctx);
5294
5295   args.device = (char *) device;
5296   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
5297         (xdrproc_t) xdr_guestfs_blockdev_getsz_args, (char *) &args);
5298   if (serial == -1) {
5299     guestfs_set_ready (g);
5300     return -1;
5301   }
5302
5303  read_reply:
5304   guestfs__switch_to_receiving (g);
5305   ctx.cb_sequence = 0;
5306   guestfs_set_reply_callback (g, blockdev_getsz_reply_cb, &ctx);
5307   (void) ml->main_loop_run (ml, g);
5308   guestfs_set_reply_callback (g, NULL, NULL);
5309   if (ctx.cb_sequence != 1001) {
5310     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz");
5311     guestfs_set_ready (g);
5312     return -1;
5313   }
5314
5315   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1) {
5316     guestfs_set_ready (g);
5317     return -1;
5318   }
5319
5320   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5321     error (g, "%s", ctx.err.error_message);
5322     guestfs_set_ready (g);
5323     return -1;
5324   }
5325
5326   guestfs_set_ready (g);
5327   return ctx.ret.sizeinsectors;
5328 }
5329
5330 struct blockdev_getsize64_ctx {
5331   /* This flag is set by the callbacks, so we know we've done
5332    * the callbacks as expected, and in the right sequence.
5333    * 0 = not called, 1 = send called,
5334    * 1001 = reply called.
5335    */
5336   int cb_sequence;
5337   struct guestfs_message_header hdr;
5338   struct guestfs_message_error err;
5339   struct guestfs_blockdev_getsize64_ret ret;
5340 };
5341
5342 static void blockdev_getsize64_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5343 {
5344   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5345   struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data;
5346
5347   ml->main_loop_quit (ml, g);
5348
5349   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5350     error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64");
5351     return;
5352   }
5353   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5354     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5355       error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64");
5356       return;
5357     }
5358     goto done;
5359   }
5360   if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &ctx->ret)) {
5361     error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64");
5362     return;
5363   }
5364  done:
5365   ctx->cb_sequence = 1001;
5366 }
5367
5368 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
5369                 const char *device)
5370 {
5371   struct guestfs_blockdev_getsize64_args args;
5372   struct blockdev_getsize64_ctx ctx;
5373   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5374   int serial;
5375
5376   if (check_state (g, "guestfs_blockdev_getsize64") == -1) return -1;
5377   guestfs_set_busy (g);
5378
5379   memset (&ctx, 0, sizeof ctx);
5380
5381   args.device = (char *) device;
5382   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
5383         (xdrproc_t) xdr_guestfs_blockdev_getsize64_args, (char *) &args);
5384   if (serial == -1) {
5385     guestfs_set_ready (g);
5386     return -1;
5387   }
5388
5389  read_reply:
5390   guestfs__switch_to_receiving (g);
5391   ctx.cb_sequence = 0;
5392   guestfs_set_reply_callback (g, blockdev_getsize64_reply_cb, &ctx);
5393   (void) ml->main_loop_run (ml, g);
5394   guestfs_set_reply_callback (g, NULL, NULL);
5395   if (ctx.cb_sequence != 1001) {
5396     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64");
5397     guestfs_set_ready (g);
5398     return -1;
5399   }
5400
5401   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1) {
5402     guestfs_set_ready (g);
5403     return -1;
5404   }
5405
5406   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5407     error (g, "%s", ctx.err.error_message);
5408     guestfs_set_ready (g);
5409     return -1;
5410   }
5411
5412   guestfs_set_ready (g);
5413   return ctx.ret.sizeinbytes;
5414 }
5415
5416 struct blockdev_flushbufs_ctx {
5417   /* This flag is set by the callbacks, so we know we've done
5418    * the callbacks as expected, and in the right sequence.
5419    * 0 = not called, 1 = send called,
5420    * 1001 = reply called.
5421    */
5422   int cb_sequence;
5423   struct guestfs_message_header hdr;
5424   struct guestfs_message_error err;
5425 };
5426
5427 static void blockdev_flushbufs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5428 {
5429   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5430   struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data;
5431
5432   ml->main_loop_quit (ml, g);
5433
5434   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5435     error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs");
5436     return;
5437   }
5438   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5439     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5440       error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs");
5441       return;
5442     }
5443     goto done;
5444   }
5445  done:
5446   ctx->cb_sequence = 1001;
5447 }
5448
5449 int guestfs_blockdev_flushbufs (guestfs_h *g,
5450                 const char *device)
5451 {
5452   struct guestfs_blockdev_flushbufs_args args;
5453   struct blockdev_flushbufs_ctx ctx;
5454   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5455   int serial;
5456
5457   if (check_state (g, "guestfs_blockdev_flushbufs") == -1) return -1;
5458   guestfs_set_busy (g);
5459
5460   memset (&ctx, 0, sizeof ctx);
5461
5462   args.device = (char *) device;
5463   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
5464         (xdrproc_t) xdr_guestfs_blockdev_flushbufs_args, (char *) &args);
5465   if (serial == -1) {
5466     guestfs_set_ready (g);
5467     return -1;
5468   }
5469
5470  read_reply:
5471   guestfs__switch_to_receiving (g);
5472   ctx.cb_sequence = 0;
5473   guestfs_set_reply_callback (g, blockdev_flushbufs_reply_cb, &ctx);
5474   (void) ml->main_loop_run (ml, g);
5475   guestfs_set_reply_callback (g, NULL, NULL);
5476   if (ctx.cb_sequence != 1001) {
5477     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs");
5478     guestfs_set_ready (g);
5479     return -1;
5480   }
5481
5482   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1) {
5483     guestfs_set_ready (g);
5484     return -1;
5485   }
5486
5487   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5488     error (g, "%s", ctx.err.error_message);
5489     guestfs_set_ready (g);
5490     return -1;
5491   }
5492
5493   guestfs_set_ready (g);
5494   return 0;
5495 }
5496
5497 struct blockdev_rereadpt_ctx {
5498   /* This flag is set by the callbacks, so we know we've done
5499    * the callbacks as expected, and in the right sequence.
5500    * 0 = not called, 1 = send called,
5501    * 1001 = reply called.
5502    */
5503   int cb_sequence;
5504   struct guestfs_message_header hdr;
5505   struct guestfs_message_error err;
5506 };
5507
5508 static void blockdev_rereadpt_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5509 {
5510   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5511   struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data;
5512
5513   ml->main_loop_quit (ml, g);
5514
5515   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5516     error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt");
5517     return;
5518   }
5519   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5520     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5521       error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt");
5522       return;
5523     }
5524     goto done;
5525   }
5526  done:
5527   ctx->cb_sequence = 1001;
5528 }
5529
5530 int guestfs_blockdev_rereadpt (guestfs_h *g,
5531                 const char *device)
5532 {
5533   struct guestfs_blockdev_rereadpt_args args;
5534   struct blockdev_rereadpt_ctx ctx;
5535   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5536   int serial;
5537
5538   if (check_state (g, "guestfs_blockdev_rereadpt") == -1) return -1;
5539   guestfs_set_busy (g);
5540
5541   memset (&ctx, 0, sizeof ctx);
5542
5543   args.device = (char *) device;
5544   serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
5545         (xdrproc_t) xdr_guestfs_blockdev_rereadpt_args, (char *) &args);
5546   if (serial == -1) {
5547     guestfs_set_ready (g);
5548     return -1;
5549   }
5550
5551  read_reply:
5552   guestfs__switch_to_receiving (g);
5553   ctx.cb_sequence = 0;
5554   guestfs_set_reply_callback (g, blockdev_rereadpt_reply_cb, &ctx);
5555   (void) ml->main_loop_run (ml, g);
5556   guestfs_set_reply_callback (g, NULL, NULL);
5557   if (ctx.cb_sequence != 1001) {
5558     error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt");
5559     guestfs_set_ready (g);
5560     return -1;
5561   }
5562
5563   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1) {
5564     guestfs_set_ready (g);
5565     return -1;
5566   }
5567
5568   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5569     error (g, "%s", ctx.err.error_message);
5570     guestfs_set_ready (g);
5571     return -1;
5572   }
5573
5574   guestfs_set_ready (g);
5575   return 0;
5576 }
5577
5578 struct upload_ctx {
5579   /* This flag is set by the callbacks, so we know we've done
5580    * the callbacks as expected, and in the right sequence.
5581    * 0 = not called, 1 = send called,
5582    * 1001 = reply called.
5583    */
5584   int cb_sequence;
5585   struct guestfs_message_header hdr;
5586   struct guestfs_message_error err;
5587 };
5588
5589 static void upload_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5590 {
5591   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5592   struct upload_ctx *ctx = (struct upload_ctx *) data;
5593
5594   ml->main_loop_quit (ml, g);
5595
5596   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5597     error (g, "%s: failed to parse reply header", "guestfs_upload");
5598     return;
5599   }
5600   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5601     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5602       error (g, "%s: failed to parse reply error", "guestfs_upload");
5603       return;
5604     }
5605     goto done;
5606   }
5607  done:
5608   ctx->cb_sequence = 1001;
5609 }
5610
5611 int guestfs_upload (guestfs_h *g,
5612                 const char *filename,
5613                 const char *remotefilename)
5614 {
5615   struct guestfs_upload_args args;
5616   struct upload_ctx ctx;
5617   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5618   int serial;
5619
5620   if (check_state (g, "guestfs_upload") == -1) return -1;
5621   guestfs_set_busy (g);
5622
5623   memset (&ctx, 0, sizeof ctx);
5624
5625   args.remotefilename = (char *) remotefilename;
5626   serial = guestfs__send_sync (g, GUESTFS_PROC_UPLOAD,
5627         (xdrproc_t) xdr_guestfs_upload_args, (char *) &args);
5628   if (serial == -1) {
5629     guestfs_set_ready (g);
5630     return -1;
5631   }
5632
5633   {
5634     int r;
5635
5636     r = guestfs__send_file_sync (g, filename);
5637     if (r == -1) {
5638       guestfs_set_ready (g);
5639       return -1;
5640     }
5641     if (r == -2) /* daemon cancelled */
5642       goto read_reply;
5643   }
5644
5645  read_reply:
5646   guestfs__switch_to_receiving (g);
5647   ctx.cb_sequence = 0;
5648   guestfs_set_reply_callback (g, upload_reply_cb, &ctx);
5649   (void) ml->main_loop_run (ml, g);
5650   guestfs_set_reply_callback (g, NULL, NULL);
5651   if (ctx.cb_sequence != 1001) {
5652     error (g, "%s reply failed, see earlier error messages", "guestfs_upload");
5653     guestfs_set_ready (g);
5654     return -1;
5655   }
5656
5657   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UPLOAD, serial) == -1) {
5658     guestfs_set_ready (g);
5659     return -1;
5660   }
5661
5662   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5663     error (g, "%s", ctx.err.error_message);
5664     guestfs_set_ready (g);
5665     return -1;
5666   }
5667
5668   guestfs_set_ready (g);
5669   return 0;
5670 }
5671
5672 struct download_ctx {
5673   /* This flag is set by the callbacks, so we know we've done
5674    * the callbacks as expected, and in the right sequence.
5675    * 0 = not called, 1 = send called,
5676    * 1001 = reply called.
5677    */
5678   int cb_sequence;
5679   struct guestfs_message_header hdr;
5680   struct guestfs_message_error err;
5681 };
5682
5683 static void download_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5684 {
5685   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5686   struct download_ctx *ctx = (struct download_ctx *) data;
5687
5688   ml->main_loop_quit (ml, g);
5689
5690   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5691     error (g, "%s: failed to parse reply header", "guestfs_download");
5692     return;
5693   }
5694   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5695     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5696       error (g, "%s: failed to parse reply error", "guestfs_download");
5697       return;
5698     }
5699     goto done;
5700   }
5701  done:
5702   ctx->cb_sequence = 1001;
5703 }
5704
5705 int guestfs_download (guestfs_h *g,
5706                 const char *remotefilename,
5707                 const char *filename)
5708 {
5709   struct guestfs_download_args args;
5710   struct download_ctx ctx;
5711   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5712   int serial;
5713
5714   if (check_state (g, "guestfs_download") == -1) return -1;
5715   guestfs_set_busy (g);
5716
5717   memset (&ctx, 0, sizeof ctx);
5718
5719   args.remotefilename = (char *) remotefilename;
5720   serial = guestfs__send_sync (g, GUESTFS_PROC_DOWNLOAD,
5721         (xdrproc_t) xdr_guestfs_download_args, (char *) &args);
5722   if (serial == -1) {
5723     guestfs_set_ready (g);
5724     return -1;
5725   }
5726
5727  read_reply:
5728   guestfs__switch_to_receiving (g);
5729   ctx.cb_sequence = 0;
5730   guestfs_set_reply_callback (g, download_reply_cb, &ctx);
5731   (void) ml->main_loop_run (ml, g);
5732   guestfs_set_reply_callback (g, NULL, NULL);
5733   if (ctx.cb_sequence != 1001) {
5734     error (g, "%s reply failed, see earlier error messages", "guestfs_download");
5735     guestfs_set_ready (g);
5736     return -1;
5737   }
5738
5739   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1) {
5740     guestfs_set_ready (g);
5741     return -1;
5742   }
5743
5744   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5745     error (g, "%s", ctx.err.error_message);
5746     guestfs_set_ready (g);
5747     return -1;
5748   }
5749
5750   if (guestfs__receive_file_sync (g, filename) == -1) {
5751     guestfs_set_ready (g);
5752     return -1;
5753   }
5754
5755   guestfs_set_ready (g);
5756   return 0;
5757 }
5758
5759 struct checksum_ctx {
5760   /* This flag is set by the callbacks, so we know we've done
5761    * the callbacks as expected, and in the right sequence.
5762    * 0 = not called, 1 = send called,
5763    * 1001 = reply called.
5764    */
5765   int cb_sequence;
5766   struct guestfs_message_header hdr;
5767   struct guestfs_message_error err;
5768   struct guestfs_checksum_ret ret;
5769 };
5770
5771 static void checksum_reply_cb (guestfs_h *g, void *data, XDR *xdr)
5772 {
5773   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5774   struct checksum_ctx *ctx = (struct checksum_ctx *) data;
5775
5776   ml->main_loop_quit (ml, g);
5777
5778   if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
5779     error (g, "%s: failed to parse reply header", "guestfs_checksum");
5780     return;
5781   }
5782   if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
5783     if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
5784       error (g, "%s: failed to parse reply error", "guestfs_checksum");
5785       return;
5786     }
5787     goto done;
5788   }
5789   if (!xdr_guestfs_checksum_ret (xdr, &ctx->ret)) {
5790     error (g, "%s: failed to parse reply", "guestfs_checksum");
5791     return;
5792   }
5793  done:
5794   ctx->cb_sequence = 1001;
5795 }
5796
5797 char *guestfs_checksum (guestfs_h *g,
5798                 const char *csumtype,
5799                 const char *path)
5800 {
5801   struct guestfs_checksum_args args;
5802   struct checksum_ctx ctx;
5803   guestfs_main_loop *ml = guestfs_get_main_loop (g);
5804   int serial;
5805
5806   if (check_state (g, "guestfs_checksum") == -1) return NULL;
5807   guestfs_set_busy (g);
5808
5809   memset (&ctx, 0, sizeof ctx);
5810
5811   args.csumtype = (char *) csumtype;
5812   args.path = (char *) path;
5813   serial = guestfs__send_sync (g, GUESTFS_PROC_CHECKSUM,
5814         (xdrproc_t) xdr_guestfs_checksum_args, (char *) &args);
5815   if (serial == -1) {
5816     guestfs_set_ready (g);
5817     return NULL;
5818   }
5819
5820  read_reply:
5821   guestfs__switch_to_receiving (g);
5822   ctx.cb_sequence = 0;
5823   guestfs_set_reply_callback (g, checksum_reply_cb, &ctx);
5824   (void) ml->main_loop_run (ml, g);
5825   guestfs_set_reply_callback (g, NULL, NULL);
5826   if (ctx.cb_sequence != 1001) {
5827     error (g, "%s reply failed, see earlier error messages", "guestfs_checksum");
5828     guestfs_set_ready (g);
5829     return NULL;
5830   }
5831
5832   if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHECKSUM, serial) == -1) {
5833     guestfs_set_ready (g);
5834     return NULL;
5835   }
5836
5837   if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
5838     error (g, "%s", ctx.err.error_message);
5839     guestfs_set_ready (g);
5840     return NULL;
5841   }
5842
5843   guestfs_set_ready (g);
5844   return ctx.ret.checksum; /* caller will free */
5845 }
5846