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