Generated files for previous commands.
[libguestfs.git] / daemon / stubs.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 program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #define _GNU_SOURCE // for strchrnul
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
28 #include <ctype.h>
29 #include <rpc/types.h>
30 #include <rpc/xdr.h>
31
32 #include "daemon.h"
33 #include "../src/guestfs_protocol.h"
34 #include "actions.h"
35
36 static void mount_stub (XDR *xdr_in)
37 {
38   int r;
39   struct guestfs_mount_args args;
40   const char *device;
41   const char *mountpoint;
42
43   memset (&args, 0, sizeof args);
44
45   if (!xdr_guestfs_mount_args (xdr_in, &args)) {
46     reply_with_error ("%s: daemon failed to decode procedure arguments", "mount");
47     return;
48   }
49   device = args.device;
50   mountpoint = args.mountpoint;
51
52   r = do_mount (device, mountpoint);
53   if (r == -1)
54     /* do_mount has already called reply_with_error, so just return */
55     return;
56
57   reply (NULL, NULL);
58 }
59
60 static void sync_stub (XDR *xdr_in)
61 {
62   int r;
63
64   r = do_sync ();
65   if (r == -1)
66     /* do_sync has already called reply_with_error, so just return */
67     return;
68
69   reply (NULL, NULL);
70 }
71
72 static void touch_stub (XDR *xdr_in)
73 {
74   int r;
75   struct guestfs_touch_args args;
76   const char *path;
77
78   memset (&args, 0, sizeof args);
79
80   if (!xdr_guestfs_touch_args (xdr_in, &args)) {
81     reply_with_error ("%s: daemon failed to decode procedure arguments", "touch");
82     return;
83   }
84   path = args.path;
85
86   r = do_touch (path);
87   if (r == -1)
88     /* do_touch has already called reply_with_error, so just return */
89     return;
90
91   reply (NULL, NULL);
92 }
93
94 static void cat_stub (XDR *xdr_in)
95 {
96   char *r;
97   struct guestfs_cat_args args;
98   const char *path;
99
100   memset (&args, 0, sizeof args);
101
102   if (!xdr_guestfs_cat_args (xdr_in, &args)) {
103     reply_with_error ("%s: daemon failed to decode procedure arguments", "cat");
104     return;
105   }
106   path = args.path;
107
108   r = do_cat (path);
109   if (r == NULL)
110     /* do_cat has already called reply_with_error, so just return */
111     return;
112
113   struct guestfs_cat_ret ret;
114   ret.content = r;
115   reply ((xdrproc_t) &xdr_guestfs_cat_ret, (char *) &ret);
116   free (r);
117 }
118
119 static void ll_stub (XDR *xdr_in)
120 {
121   char *r;
122   struct guestfs_ll_args args;
123   const char *directory;
124
125   memset (&args, 0, sizeof args);
126
127   if (!xdr_guestfs_ll_args (xdr_in, &args)) {
128     reply_with_error ("%s: daemon failed to decode procedure arguments", "ll");
129     return;
130   }
131   directory = args.directory;
132
133   r = do_ll (directory);
134   if (r == NULL)
135     /* do_ll has already called reply_with_error, so just return */
136     return;
137
138   struct guestfs_ll_ret ret;
139   ret.listing = r;
140   reply ((xdrproc_t) &xdr_guestfs_ll_ret, (char *) &ret);
141   free (r);
142 }
143
144 static void ls_stub (XDR *xdr_in)
145 {
146   char **r;
147   struct guestfs_ls_args args;
148   const char *directory;
149
150   memset (&args, 0, sizeof args);
151
152   if (!xdr_guestfs_ls_args (xdr_in, &args)) {
153     reply_with_error ("%s: daemon failed to decode procedure arguments", "ls");
154     return;
155   }
156   directory = args.directory;
157
158   r = do_ls (directory);
159   if (r == NULL)
160     /* do_ls has already called reply_with_error, so just return */
161     return;
162
163   struct guestfs_ls_ret ret;
164   ret.listing.listing_len = count_strings (r);
165   ret.listing.listing_val = r;
166   reply ((xdrproc_t) &xdr_guestfs_ls_ret, (char *) &ret);
167   free_strings (r);
168 }
169
170 static void list_devices_stub (XDR *xdr_in)
171 {
172   char **r;
173
174   r = do_list_devices ();
175   if (r == NULL)
176     /* do_list_devices has already called reply_with_error, so just return */
177     return;
178
179   struct guestfs_list_devices_ret ret;
180   ret.devices.devices_len = count_strings (r);
181   ret.devices.devices_val = r;
182   reply ((xdrproc_t) &xdr_guestfs_list_devices_ret, (char *) &ret);
183   free_strings (r);
184 }
185
186 static void list_partitions_stub (XDR *xdr_in)
187 {
188   char **r;
189
190   r = do_list_partitions ();
191   if (r == NULL)
192     /* do_list_partitions has already called reply_with_error, so just return */
193     return;
194
195   struct guestfs_list_partitions_ret ret;
196   ret.partitions.partitions_len = count_strings (r);
197   ret.partitions.partitions_val = r;
198   reply ((xdrproc_t) &xdr_guestfs_list_partitions_ret, (char *) &ret);
199   free_strings (r);
200 }
201
202 static void pvs_stub (XDR *xdr_in)
203 {
204   char **r;
205
206   r = do_pvs ();
207   if (r == NULL)
208     /* do_pvs has already called reply_with_error, so just return */
209     return;
210
211   struct guestfs_pvs_ret ret;
212   ret.physvols.physvols_len = count_strings (r);
213   ret.physvols.physvols_val = r;
214   reply ((xdrproc_t) &xdr_guestfs_pvs_ret, (char *) &ret);
215   free_strings (r);
216 }
217
218 static void vgs_stub (XDR *xdr_in)
219 {
220   char **r;
221
222   r = do_vgs ();
223   if (r == NULL)
224     /* do_vgs has already called reply_with_error, so just return */
225     return;
226
227   struct guestfs_vgs_ret ret;
228   ret.volgroups.volgroups_len = count_strings (r);
229   ret.volgroups.volgroups_val = r;
230   reply ((xdrproc_t) &xdr_guestfs_vgs_ret, (char *) &ret);
231   free_strings (r);
232 }
233
234 static void lvs_stub (XDR *xdr_in)
235 {
236   char **r;
237
238   r = do_lvs ();
239   if (r == NULL)
240     /* do_lvs has already called reply_with_error, so just return */
241     return;
242
243   struct guestfs_lvs_ret ret;
244   ret.logvols.logvols_len = count_strings (r);
245   ret.logvols.logvols_val = r;
246   reply ((xdrproc_t) &xdr_guestfs_lvs_ret, (char *) &ret);
247   free_strings (r);
248 }
249
250 static void pvs_full_stub (XDR *xdr_in)
251 {
252   guestfs_lvm_int_pv_list *r;
253
254   r = do_pvs_full ();
255   if (r == NULL)
256     /* do_pvs_full has already called reply_with_error, so just return */
257     return;
258
259   struct guestfs_pvs_full_ret ret;
260   ret.physvols = *r;
261   reply ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret);
262   xdr_free ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret);
263 }
264
265 static void vgs_full_stub (XDR *xdr_in)
266 {
267   guestfs_lvm_int_vg_list *r;
268
269   r = do_vgs_full ();
270   if (r == NULL)
271     /* do_vgs_full has already called reply_with_error, so just return */
272     return;
273
274   struct guestfs_vgs_full_ret ret;
275   ret.volgroups = *r;
276   reply ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret);
277   xdr_free ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret);
278 }
279
280 static void lvs_full_stub (XDR *xdr_in)
281 {
282   guestfs_lvm_int_lv_list *r;
283
284   r = do_lvs_full ();
285   if (r == NULL)
286     /* do_lvs_full has already called reply_with_error, so just return */
287     return;
288
289   struct guestfs_lvs_full_ret ret;
290   ret.logvols = *r;
291   reply ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret);
292   xdr_free ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret);
293 }
294
295 static void read_lines_stub (XDR *xdr_in)
296 {
297   char **r;
298   struct guestfs_read_lines_args args;
299   const char *path;
300
301   memset (&args, 0, sizeof args);
302
303   if (!xdr_guestfs_read_lines_args (xdr_in, &args)) {
304     reply_with_error ("%s: daemon failed to decode procedure arguments", "read_lines");
305     return;
306   }
307   path = args.path;
308
309   r = do_read_lines (path);
310   if (r == NULL)
311     /* do_read_lines has already called reply_with_error, so just return */
312     return;
313
314   struct guestfs_read_lines_ret ret;
315   ret.lines.lines_len = count_strings (r);
316   ret.lines.lines_val = r;
317   reply ((xdrproc_t) &xdr_guestfs_read_lines_ret, (char *) &ret);
318   free_strings (r);
319 }
320
321 static void aug_init_stub (XDR *xdr_in)
322 {
323   int r;
324   struct guestfs_aug_init_args args;
325   const char *root;
326   int flags;
327
328   memset (&args, 0, sizeof args);
329
330   if (!xdr_guestfs_aug_init_args (xdr_in, &args)) {
331     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_init");
332     return;
333   }
334   root = args.root;
335   flags = args.flags;
336
337   r = do_aug_init (root, flags);
338   if (r == -1)
339     /* do_aug_init has already called reply_with_error, so just return */
340     return;
341
342   reply (NULL, NULL);
343 }
344
345 static void aug_close_stub (XDR *xdr_in)
346 {
347   int r;
348
349   r = do_aug_close ();
350   if (r == -1)
351     /* do_aug_close has already called reply_with_error, so just return */
352     return;
353
354   reply (NULL, NULL);
355 }
356
357 static void aug_defvar_stub (XDR *xdr_in)
358 {
359   int r;
360   struct guestfs_aug_defvar_args args;
361   const char *name;
362   const char *expr;
363
364   memset (&args, 0, sizeof args);
365
366   if (!xdr_guestfs_aug_defvar_args (xdr_in, &args)) {
367     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_defvar");
368     return;
369   }
370   name = args.name;
371   expr = args.expr ? *args.expr : NULL;
372
373   r = do_aug_defvar (name, expr);
374   if (r == -1)
375     /* do_aug_defvar has already called reply_with_error, so just return */
376     return;
377
378   struct guestfs_aug_defvar_ret ret;
379   ret.nrnodes = r;
380   reply ((xdrproc_t) &xdr_guestfs_aug_defvar_ret, (char *) &ret);
381 }
382
383 static void aug_defnode_stub (XDR *xdr_in)
384 {
385   guestfs_aug_defnode_ret *r;
386   struct guestfs_aug_defnode_args args;
387   const char *name;
388   const char *expr;
389   const char *val;
390
391   memset (&args, 0, sizeof args);
392
393   if (!xdr_guestfs_aug_defnode_args (xdr_in, &args)) {
394     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_defnode");
395     return;
396   }
397   name = args.name;
398   expr = args.expr;
399   val = args.val;
400
401   r = do_aug_defnode (name, expr, val);
402   if (r == NULL)
403     /* do_aug_defnode has already called reply_with_error, so just return */
404     return;
405
406   reply ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r);
407   xdr_free ((xdrproc_t) xdr_guestfs_aug_defnode_ret, (char *) r);
408 }
409
410 static void aug_get_stub (XDR *xdr_in)
411 {
412   char *r;
413   struct guestfs_aug_get_args args;
414   const char *path;
415
416   memset (&args, 0, sizeof args);
417
418   if (!xdr_guestfs_aug_get_args (xdr_in, &args)) {
419     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_get");
420     return;
421   }
422   path = args.path;
423
424   r = do_aug_get (path);
425   if (r == NULL)
426     /* do_aug_get has already called reply_with_error, so just return */
427     return;
428
429   struct guestfs_aug_get_ret ret;
430   ret.val = r;
431   reply ((xdrproc_t) &xdr_guestfs_aug_get_ret, (char *) &ret);
432   free (r);
433 }
434
435 static void aug_set_stub (XDR *xdr_in)
436 {
437   int r;
438   struct guestfs_aug_set_args args;
439   const char *path;
440   const char *val;
441
442   memset (&args, 0, sizeof args);
443
444   if (!xdr_guestfs_aug_set_args (xdr_in, &args)) {
445     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_set");
446     return;
447   }
448   path = args.path;
449   val = args.val;
450
451   r = do_aug_set (path, val);
452   if (r == -1)
453     /* do_aug_set has already called reply_with_error, so just return */
454     return;
455
456   reply (NULL, NULL);
457 }
458
459 static void aug_insert_stub (XDR *xdr_in)
460 {
461   int r;
462   struct guestfs_aug_insert_args args;
463   const char *path;
464   const char *label;
465   int before;
466
467   memset (&args, 0, sizeof args);
468
469   if (!xdr_guestfs_aug_insert_args (xdr_in, &args)) {
470     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_insert");
471     return;
472   }
473   path = args.path;
474   label = args.label;
475   before = args.before;
476
477   r = do_aug_insert (path, label, before);
478   if (r == -1)
479     /* do_aug_insert has already called reply_with_error, so just return */
480     return;
481
482   reply (NULL, NULL);
483 }
484
485 static void aug_rm_stub (XDR *xdr_in)
486 {
487   int r;
488   struct guestfs_aug_rm_args args;
489   const char *path;
490
491   memset (&args, 0, sizeof args);
492
493   if (!xdr_guestfs_aug_rm_args (xdr_in, &args)) {
494     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_rm");
495     return;
496   }
497   path = args.path;
498
499   r = do_aug_rm (path);
500   if (r == -1)
501     /* do_aug_rm has already called reply_with_error, so just return */
502     return;
503
504   struct guestfs_aug_rm_ret ret;
505   ret.nrnodes = r;
506   reply ((xdrproc_t) &xdr_guestfs_aug_rm_ret, (char *) &ret);
507 }
508
509 static void aug_mv_stub (XDR *xdr_in)
510 {
511   int r;
512   struct guestfs_aug_mv_args args;
513   const char *src;
514   const char *dest;
515
516   memset (&args, 0, sizeof args);
517
518   if (!xdr_guestfs_aug_mv_args (xdr_in, &args)) {
519     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_mv");
520     return;
521   }
522   src = args.src;
523   dest = args.dest;
524
525   r = do_aug_mv (src, dest);
526   if (r == -1)
527     /* do_aug_mv has already called reply_with_error, so just return */
528     return;
529
530   reply (NULL, NULL);
531 }
532
533 static void aug_match_stub (XDR *xdr_in)
534 {
535   char **r;
536   struct guestfs_aug_match_args args;
537   const char *path;
538
539   memset (&args, 0, sizeof args);
540
541   if (!xdr_guestfs_aug_match_args (xdr_in, &args)) {
542     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_match");
543     return;
544   }
545   path = args.path;
546
547   r = do_aug_match (path);
548   if (r == NULL)
549     /* do_aug_match has already called reply_with_error, so just return */
550     return;
551
552   struct guestfs_aug_match_ret ret;
553   ret.matches.matches_len = count_strings (r);
554   ret.matches.matches_val = r;
555   reply ((xdrproc_t) &xdr_guestfs_aug_match_ret, (char *) &ret);
556   free_strings (r);
557 }
558
559 static void aug_save_stub (XDR *xdr_in)
560 {
561   int r;
562
563   r = do_aug_save ();
564   if (r == -1)
565     /* do_aug_save has already called reply_with_error, so just return */
566     return;
567
568   reply (NULL, NULL);
569 }
570
571 static void aug_load_stub (XDR *xdr_in)
572 {
573   int r;
574
575   r = do_aug_load ();
576   if (r == -1)
577     /* do_aug_load has already called reply_with_error, so just return */
578     return;
579
580   reply (NULL, NULL);
581 }
582
583 static void aug_ls_stub (XDR *xdr_in)
584 {
585   char **r;
586   struct guestfs_aug_ls_args args;
587   const char *path;
588
589   memset (&args, 0, sizeof args);
590
591   if (!xdr_guestfs_aug_ls_args (xdr_in, &args)) {
592     reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_ls");
593     return;
594   }
595   path = args.path;
596
597   r = do_aug_ls (path);
598   if (r == NULL)
599     /* do_aug_ls has already called reply_with_error, so just return */
600     return;
601
602   struct guestfs_aug_ls_ret ret;
603   ret.matches.matches_len = count_strings (r);
604   ret.matches.matches_val = r;
605   reply ((xdrproc_t) &xdr_guestfs_aug_ls_ret, (char *) &ret);
606   free_strings (r);
607 }
608
609 static void rm_stub (XDR *xdr_in)
610 {
611   int r;
612   struct guestfs_rm_args args;
613   const char *path;
614
615   memset (&args, 0, sizeof args);
616
617   if (!xdr_guestfs_rm_args (xdr_in, &args)) {
618     reply_with_error ("%s: daemon failed to decode procedure arguments", "rm");
619     return;
620   }
621   path = args.path;
622
623   r = do_rm (path);
624   if (r == -1)
625     /* do_rm has already called reply_with_error, so just return */
626     return;
627
628   reply (NULL, NULL);
629 }
630
631 static void rmdir_stub (XDR *xdr_in)
632 {
633   int r;
634   struct guestfs_rmdir_args args;
635   const char *path;
636
637   memset (&args, 0, sizeof args);
638
639   if (!xdr_guestfs_rmdir_args (xdr_in, &args)) {
640     reply_with_error ("%s: daemon failed to decode procedure arguments", "rmdir");
641     return;
642   }
643   path = args.path;
644
645   r = do_rmdir (path);
646   if (r == -1)
647     /* do_rmdir has already called reply_with_error, so just return */
648     return;
649
650   reply (NULL, NULL);
651 }
652
653 static void rm_rf_stub (XDR *xdr_in)
654 {
655   int r;
656   struct guestfs_rm_rf_args args;
657   const char *path;
658
659   memset (&args, 0, sizeof args);
660
661   if (!xdr_guestfs_rm_rf_args (xdr_in, &args)) {
662     reply_with_error ("%s: daemon failed to decode procedure arguments", "rm_rf");
663     return;
664   }
665   path = args.path;
666
667   r = do_rm_rf (path);
668   if (r == -1)
669     /* do_rm_rf has already called reply_with_error, so just return */
670     return;
671
672   reply (NULL, NULL);
673 }
674
675 static void mkdir_stub (XDR *xdr_in)
676 {
677   int r;
678   struct guestfs_mkdir_args args;
679   const char *path;
680
681   memset (&args, 0, sizeof args);
682
683   if (!xdr_guestfs_mkdir_args (xdr_in, &args)) {
684     reply_with_error ("%s: daemon failed to decode procedure arguments", "mkdir");
685     return;
686   }
687   path = args.path;
688
689   r = do_mkdir (path);
690   if (r == -1)
691     /* do_mkdir has already called reply_with_error, so just return */
692     return;
693
694   reply (NULL, NULL);
695 }
696
697 static void mkdir_p_stub (XDR *xdr_in)
698 {
699   int r;
700   struct guestfs_mkdir_p_args args;
701   const char *path;
702
703   memset (&args, 0, sizeof args);
704
705   if (!xdr_guestfs_mkdir_p_args (xdr_in, &args)) {
706     reply_with_error ("%s: daemon failed to decode procedure arguments", "mkdir_p");
707     return;
708   }
709   path = args.path;
710
711   r = do_mkdir_p (path);
712   if (r == -1)
713     /* do_mkdir_p has already called reply_with_error, so just return */
714     return;
715
716   reply (NULL, NULL);
717 }
718
719 static void chmod_stub (XDR *xdr_in)
720 {
721   int r;
722   struct guestfs_chmod_args args;
723   int mode;
724   const char *path;
725
726   memset (&args, 0, sizeof args);
727
728   if (!xdr_guestfs_chmod_args (xdr_in, &args)) {
729     reply_with_error ("%s: daemon failed to decode procedure arguments", "chmod");
730     return;
731   }
732   mode = args.mode;
733   path = args.path;
734
735   r = do_chmod (mode, path);
736   if (r == -1)
737     /* do_chmod has already called reply_with_error, so just return */
738     return;
739
740   reply (NULL, NULL);
741 }
742
743 static void chown_stub (XDR *xdr_in)
744 {
745   int r;
746   struct guestfs_chown_args args;
747   int owner;
748   int group;
749   const char *path;
750
751   memset (&args, 0, sizeof args);
752
753   if (!xdr_guestfs_chown_args (xdr_in, &args)) {
754     reply_with_error ("%s: daemon failed to decode procedure arguments", "chown");
755     return;
756   }
757   owner = args.owner;
758   group = args.group;
759   path = args.path;
760
761   r = do_chown (owner, group, path);
762   if (r == -1)
763     /* do_chown has already called reply_with_error, so just return */
764     return;
765
766   reply (NULL, NULL);
767 }
768
769 void dispatch_incoming_message (XDR *xdr_in)
770 {
771   switch (proc_nr) {
772     case GUESTFS_PROC_MOUNT:
773       mount_stub (xdr_in);
774       break;
775     case GUESTFS_PROC_SYNC:
776       sync_stub (xdr_in);
777       break;
778     case GUESTFS_PROC_TOUCH:
779       touch_stub (xdr_in);
780       break;
781     case GUESTFS_PROC_CAT:
782       cat_stub (xdr_in);
783       break;
784     case GUESTFS_PROC_LL:
785       ll_stub (xdr_in);
786       break;
787     case GUESTFS_PROC_LS:
788       ls_stub (xdr_in);
789       break;
790     case GUESTFS_PROC_LIST_DEVICES:
791       list_devices_stub (xdr_in);
792       break;
793     case GUESTFS_PROC_LIST_PARTITIONS:
794       list_partitions_stub (xdr_in);
795       break;
796     case GUESTFS_PROC_PVS:
797       pvs_stub (xdr_in);
798       break;
799     case GUESTFS_PROC_VGS:
800       vgs_stub (xdr_in);
801       break;
802     case GUESTFS_PROC_LVS:
803       lvs_stub (xdr_in);
804       break;
805     case GUESTFS_PROC_PVS_FULL:
806       pvs_full_stub (xdr_in);
807       break;
808     case GUESTFS_PROC_VGS_FULL:
809       vgs_full_stub (xdr_in);
810       break;
811     case GUESTFS_PROC_LVS_FULL:
812       lvs_full_stub (xdr_in);
813       break;
814     case GUESTFS_PROC_READ_LINES:
815       read_lines_stub (xdr_in);
816       break;
817     case GUESTFS_PROC_AUG_INIT:
818       aug_init_stub (xdr_in);
819       break;
820     case GUESTFS_PROC_AUG_CLOSE:
821       aug_close_stub (xdr_in);
822       break;
823     case GUESTFS_PROC_AUG_DEFVAR:
824       aug_defvar_stub (xdr_in);
825       break;
826     case GUESTFS_PROC_AUG_DEFNODE:
827       aug_defnode_stub (xdr_in);
828       break;
829     case GUESTFS_PROC_AUG_GET:
830       aug_get_stub (xdr_in);
831       break;
832     case GUESTFS_PROC_AUG_SET:
833       aug_set_stub (xdr_in);
834       break;
835     case GUESTFS_PROC_AUG_INSERT:
836       aug_insert_stub (xdr_in);
837       break;
838     case GUESTFS_PROC_AUG_RM:
839       aug_rm_stub (xdr_in);
840       break;
841     case GUESTFS_PROC_AUG_MV:
842       aug_mv_stub (xdr_in);
843       break;
844     case GUESTFS_PROC_AUG_MATCH:
845       aug_match_stub (xdr_in);
846       break;
847     case GUESTFS_PROC_AUG_SAVE:
848       aug_save_stub (xdr_in);
849       break;
850     case GUESTFS_PROC_AUG_LOAD:
851       aug_load_stub (xdr_in);
852       break;
853     case GUESTFS_PROC_AUG_LS:
854       aug_ls_stub (xdr_in);
855       break;
856     case GUESTFS_PROC_RM:
857       rm_stub (xdr_in);
858       break;
859     case GUESTFS_PROC_RMDIR:
860       rmdir_stub (xdr_in);
861       break;
862     case GUESTFS_PROC_RM_RF:
863       rm_rf_stub (xdr_in);
864       break;
865     case GUESTFS_PROC_MKDIR:
866       mkdir_stub (xdr_in);
867       break;
868     case GUESTFS_PROC_MKDIR_P:
869       mkdir_p_stub (xdr_in);
870       break;
871     case GUESTFS_PROC_CHMOD:
872       chmod_stub (xdr_in);
873       break;
874     case GUESTFS_PROC_CHOWN:
875       chown_stub (xdr_in);
876       break;
877     default:
878       reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
879   }
880 }
881
882 static const char *lvm_pv_cols = "pv_name,pv_uuid,pv_fmt,pv_size,dev_size,pv_free,pv_used,pv_attr,pv_pe_count,pv_pe_alloc_count,pv_tags,pe_start,pv_mda_count,pv_mda_free";
883
884 static int lvm_tokenize_pv (char *str, struct guestfs_lvm_int_pv *r)
885 {
886   char *tok, *p, *next;
887   int i, j;
888
889   if (!str) {
890     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
891     return -1;
892   }
893   if (!*str || isspace (*str)) {
894     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
895     return -1;
896   }
897   tok = str;
898   if (!tok) {
899     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_name");
900     return -1;
901   }
902   p = strchrnul (tok, ',');
903   if (*p) next = p+1; else next = NULL;
904   *p = '\0';
905   r->pv_name = strdup (tok);
906   if (r->pv_name == NULL) {
907     perror ("strdup");
908     return -1;
909   }
910   tok = next;
911   if (!tok) {
912     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_uuid");
913     return -1;
914   }
915   p = strchrnul (tok, ',');
916   if (*p) next = p+1; else next = NULL;
917   *p = '\0';
918   for (i = j = 0; i < 32; ++j) {
919     if (tok[j] == '\0') {
920       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
921       return -1;
922     } else if (tok[j] != '-')
923       r->pv_uuid[i++] = tok[j];
924   }
925   tok = next;
926   if (!tok) {
927     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_fmt");
928     return -1;
929   }
930   p = strchrnul (tok, ',');
931   if (*p) next = p+1; else next = NULL;
932   *p = '\0';
933   r->pv_fmt = strdup (tok);
934   if (r->pv_fmt == NULL) {
935     perror ("strdup");
936     return -1;
937   }
938   tok = next;
939   if (!tok) {
940     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_size");
941     return -1;
942   }
943   p = strchrnul (tok, ',');
944   if (*p) next = p+1; else next = NULL;
945   *p = '\0';
946   if (sscanf (tok, "%"SCNu64, &r->pv_size) != 1) {
947     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_size");
948     return -1;
949   }
950   tok = next;
951   if (!tok) {
952     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "dev_size");
953     return -1;
954   }
955   p = strchrnul (tok, ',');
956   if (*p) next = p+1; else next = NULL;
957   *p = '\0';
958   if (sscanf (tok, "%"SCNu64, &r->dev_size) != 1) {
959     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "dev_size");
960     return -1;
961   }
962   tok = next;
963   if (!tok) {
964     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_free");
965     return -1;
966   }
967   p = strchrnul (tok, ',');
968   if (*p) next = p+1; else next = NULL;
969   *p = '\0';
970   if (sscanf (tok, "%"SCNu64, &r->pv_free) != 1) {
971     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_free");
972     return -1;
973   }
974   tok = next;
975   if (!tok) {
976     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_used");
977     return -1;
978   }
979   p = strchrnul (tok, ',');
980   if (*p) next = p+1; else next = NULL;
981   *p = '\0';
982   if (sscanf (tok, "%"SCNu64, &r->pv_used) != 1) {
983     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_used");
984     return -1;
985   }
986   tok = next;
987   if (!tok) {
988     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_attr");
989     return -1;
990   }
991   p = strchrnul (tok, ',');
992   if (*p) next = p+1; else next = NULL;
993   *p = '\0';
994   r->pv_attr = strdup (tok);
995   if (r->pv_attr == NULL) {
996     perror ("strdup");
997     return -1;
998   }
999   tok = next;
1000   if (!tok) {
1001     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_pe_count");
1002     return -1;
1003   }
1004   p = strchrnul (tok, ',');
1005   if (*p) next = p+1; else next = NULL;
1006   *p = '\0';
1007   if (sscanf (tok, "%"SCNi64, &r->pv_pe_count) != 1) {
1008     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_pe_count");
1009     return -1;
1010   }
1011   tok = next;
1012   if (!tok) {
1013     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_pe_alloc_count");
1014     return -1;
1015   }
1016   p = strchrnul (tok, ',');
1017   if (*p) next = p+1; else next = NULL;
1018   *p = '\0';
1019   if (sscanf (tok, "%"SCNi64, &r->pv_pe_alloc_count) != 1) {
1020     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_pe_alloc_count");
1021     return -1;
1022   }
1023   tok = next;
1024   if (!tok) {
1025     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_tags");
1026     return -1;
1027   }
1028   p = strchrnul (tok, ',');
1029   if (*p) next = p+1; else next = NULL;
1030   *p = '\0';
1031   r->pv_tags = strdup (tok);
1032   if (r->pv_tags == NULL) {
1033     perror ("strdup");
1034     return -1;
1035   }
1036   tok = next;
1037   if (!tok) {
1038     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pe_start");
1039     return -1;
1040   }
1041   p = strchrnul (tok, ',');
1042   if (*p) next = p+1; else next = NULL;
1043   *p = '\0';
1044   if (sscanf (tok, "%"SCNu64, &r->pe_start) != 1) {
1045     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pe_start");
1046     return -1;
1047   }
1048   tok = next;
1049   if (!tok) {
1050     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_mda_count");
1051     return -1;
1052   }
1053   p = strchrnul (tok, ',');
1054   if (*p) next = p+1; else next = NULL;
1055   *p = '\0';
1056   if (sscanf (tok, "%"SCNi64, &r->pv_mda_count) != 1) {
1057     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_mda_count");
1058     return -1;
1059   }
1060   tok = next;
1061   if (!tok) {
1062     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_mda_free");
1063     return -1;
1064   }
1065   p = strchrnul (tok, ',');
1066   if (*p) next = p+1; else next = NULL;
1067   *p = '\0';
1068   if (sscanf (tok, "%"SCNu64, &r->pv_mda_free) != 1) {
1069     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_mda_free");
1070     return -1;
1071   }
1072   tok = next;
1073   if (tok != NULL) {
1074     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
1075     return -1;
1076   }
1077   return 0;
1078 }
1079
1080 guestfs_lvm_int_pv_list *
1081 parse_command_line_pvs (void)
1082 {
1083   char *out, *err;
1084   char *p, *pend;
1085   int r, i;
1086   guestfs_lvm_int_pv_list *ret;
1087   void *newp;
1088
1089   ret = malloc (sizeof *ret);
1090   if (!ret) {
1091     reply_with_perror ("malloc");
1092     return NULL;
1093   }
1094
1095   ret->guestfs_lvm_int_pv_list_len = 0;
1096   ret->guestfs_lvm_int_pv_list_val = NULL;
1097
1098   r = command (&out, &err,
1099                "/sbin/lvm", "pvs",
1100                "-o", lvm_pv_cols, "--unbuffered", "--noheadings",
1101                "--nosuffix", "--separator", ",", "--units", "b", NULL);
1102   if (r == -1) {
1103     reply_with_error ("%s", err);
1104     free (out);
1105     free (err);
1106     return NULL;
1107   }
1108
1109   free (err);
1110
1111   /* Tokenize each line of the output. */
1112   p = out;
1113   i = 0;
1114   while (p) {
1115     pend = strchr (p, '\n');    /* Get the next line of output. */
1116     if (pend) {
1117       *pend = '\0';
1118       pend++;
1119     }
1120
1121     while (*p && isspace (*p))  /* Skip any leading whitespace. */
1122       p++;
1123
1124     if (!*p) {                  /* Empty line?  Skip it. */
1125       p = pend;
1126       continue;
1127     }
1128
1129     /* Allocate some space to store this next entry. */
1130     newp = realloc (ret->guestfs_lvm_int_pv_list_val,
1131                     sizeof (guestfs_lvm_int_pv) * (i+1));
1132     if (newp == NULL) {
1133       reply_with_perror ("realloc");
1134       free (ret->guestfs_lvm_int_pv_list_val);
1135       free (ret);
1136       free (out);
1137       return NULL;
1138     }
1139     ret->guestfs_lvm_int_pv_list_val = newp;
1140
1141     /* Tokenize the next entry. */
1142     r = lvm_tokenize_pv (p, &ret->guestfs_lvm_int_pv_list_val[i]);
1143     if (r == -1) {
1144       reply_with_error ("failed to parse output of 'pvs' command");
1145       free (ret->guestfs_lvm_int_pv_list_val);
1146       free (ret);
1147       free (out);
1148       return NULL;
1149     }
1150
1151     ++i;
1152     p = pend;
1153   }
1154
1155   ret->guestfs_lvm_int_pv_list_len = i;
1156
1157   free (out);
1158   return ret;
1159 }
1160 static const char *lvm_vg_cols = "vg_name,vg_uuid,vg_fmt,vg_attr,vg_size,vg_free,vg_sysid,vg_extent_size,vg_extent_count,vg_free_count,max_lv,max_pv,pv_count,lv_count,snap_count,vg_seqno,vg_tags,vg_mda_count,vg_mda_free";
1161
1162 static int lvm_tokenize_vg (char *str, struct guestfs_lvm_int_vg *r)
1163 {
1164   char *tok, *p, *next;
1165   int i, j;
1166
1167   if (!str) {
1168     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
1169     return -1;
1170   }
1171   if (!*str || isspace (*str)) {
1172     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
1173     return -1;
1174   }
1175   tok = str;
1176   if (!tok) {
1177     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_name");
1178     return -1;
1179   }
1180   p = strchrnul (tok, ',');
1181   if (*p) next = p+1; else next = NULL;
1182   *p = '\0';
1183   r->vg_name = strdup (tok);
1184   if (r->vg_name == NULL) {
1185     perror ("strdup");
1186     return -1;
1187   }
1188   tok = next;
1189   if (!tok) {
1190     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_uuid");
1191     return -1;
1192   }
1193   p = strchrnul (tok, ',');
1194   if (*p) next = p+1; else next = NULL;
1195   *p = '\0';
1196   for (i = j = 0; i < 32; ++j) {
1197     if (tok[j] == '\0') {
1198       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
1199       return -1;
1200     } else if (tok[j] != '-')
1201       r->vg_uuid[i++] = tok[j];
1202   }
1203   tok = next;
1204   if (!tok) {
1205     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_fmt");
1206     return -1;
1207   }
1208   p = strchrnul (tok, ',');
1209   if (*p) next = p+1; else next = NULL;
1210   *p = '\0';
1211   r->vg_fmt = strdup (tok);
1212   if (r->vg_fmt == NULL) {
1213     perror ("strdup");
1214     return -1;
1215   }
1216   tok = next;
1217   if (!tok) {
1218     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_attr");
1219     return -1;
1220   }
1221   p = strchrnul (tok, ',');
1222   if (*p) next = p+1; else next = NULL;
1223   *p = '\0';
1224   r->vg_attr = strdup (tok);
1225   if (r->vg_attr == NULL) {
1226     perror ("strdup");
1227     return -1;
1228   }
1229   tok = next;
1230   if (!tok) {
1231     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_size");
1232     return -1;
1233   }
1234   p = strchrnul (tok, ',');
1235   if (*p) next = p+1; else next = NULL;
1236   *p = '\0';
1237   if (sscanf (tok, "%"SCNu64, &r->vg_size) != 1) {
1238     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_size");
1239     return -1;
1240   }
1241   tok = next;
1242   if (!tok) {
1243     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_free");
1244     return -1;
1245   }
1246   p = strchrnul (tok, ',');
1247   if (*p) next = p+1; else next = NULL;
1248   *p = '\0';
1249   if (sscanf (tok, "%"SCNu64, &r->vg_free) != 1) {
1250     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_free");
1251     return -1;
1252   }
1253   tok = next;
1254   if (!tok) {
1255     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_sysid");
1256     return -1;
1257   }
1258   p = strchrnul (tok, ',');
1259   if (*p) next = p+1; else next = NULL;
1260   *p = '\0';
1261   r->vg_sysid = strdup (tok);
1262   if (r->vg_sysid == NULL) {
1263     perror ("strdup");
1264     return -1;
1265   }
1266   tok = next;
1267   if (!tok) {
1268     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_extent_size");
1269     return -1;
1270   }
1271   p = strchrnul (tok, ',');
1272   if (*p) next = p+1; else next = NULL;
1273   *p = '\0';
1274   if (sscanf (tok, "%"SCNu64, &r->vg_extent_size) != 1) {
1275     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_extent_size");
1276     return -1;
1277   }
1278   tok = next;
1279   if (!tok) {
1280     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_extent_count");
1281     return -1;
1282   }
1283   p = strchrnul (tok, ',');
1284   if (*p) next = p+1; else next = NULL;
1285   *p = '\0';
1286   if (sscanf (tok, "%"SCNi64, &r->vg_extent_count) != 1) {
1287     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_extent_count");
1288     return -1;
1289   }
1290   tok = next;
1291   if (!tok) {
1292     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_free_count");
1293     return -1;
1294   }
1295   p = strchrnul (tok, ',');
1296   if (*p) next = p+1; else next = NULL;
1297   *p = '\0';
1298   if (sscanf (tok, "%"SCNi64, &r->vg_free_count) != 1) {
1299     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_free_count");
1300     return -1;
1301   }
1302   tok = next;
1303   if (!tok) {
1304     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "max_lv");
1305     return -1;
1306   }
1307   p = strchrnul (tok, ',');
1308   if (*p) next = p+1; else next = NULL;
1309   *p = '\0';
1310   if (sscanf (tok, "%"SCNi64, &r->max_lv) != 1) {
1311     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "max_lv");
1312     return -1;
1313   }
1314   tok = next;
1315   if (!tok) {
1316     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "max_pv");
1317     return -1;
1318   }
1319   p = strchrnul (tok, ',');
1320   if (*p) next = p+1; else next = NULL;
1321   *p = '\0';
1322   if (sscanf (tok, "%"SCNi64, &r->max_pv) != 1) {
1323     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "max_pv");
1324     return -1;
1325   }
1326   tok = next;
1327   if (!tok) {
1328     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_count");
1329     return -1;
1330   }
1331   p = strchrnul (tok, ',');
1332   if (*p) next = p+1; else next = NULL;
1333   *p = '\0';
1334   if (sscanf (tok, "%"SCNi64, &r->pv_count) != 1) {
1335     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_count");
1336     return -1;
1337   }
1338   tok = next;
1339   if (!tok) {
1340     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_count");
1341     return -1;
1342   }
1343   p = strchrnul (tok, ',');
1344   if (*p) next = p+1; else next = NULL;
1345   *p = '\0';
1346   if (sscanf (tok, "%"SCNi64, &r->lv_count) != 1) {
1347     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_count");
1348     return -1;
1349   }
1350   tok = next;
1351   if (!tok) {
1352     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "snap_count");
1353     return -1;
1354   }
1355   p = strchrnul (tok, ',');
1356   if (*p) next = p+1; else next = NULL;
1357   *p = '\0';
1358   if (sscanf (tok, "%"SCNi64, &r->snap_count) != 1) {
1359     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "snap_count");
1360     return -1;
1361   }
1362   tok = next;
1363   if (!tok) {
1364     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_seqno");
1365     return -1;
1366   }
1367   p = strchrnul (tok, ',');
1368   if (*p) next = p+1; else next = NULL;
1369   *p = '\0';
1370   if (sscanf (tok, "%"SCNi64, &r->vg_seqno) != 1) {
1371     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_seqno");
1372     return -1;
1373   }
1374   tok = next;
1375   if (!tok) {
1376     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_tags");
1377     return -1;
1378   }
1379   p = strchrnul (tok, ',');
1380   if (*p) next = p+1; else next = NULL;
1381   *p = '\0';
1382   r->vg_tags = strdup (tok);
1383   if (r->vg_tags == NULL) {
1384     perror ("strdup");
1385     return -1;
1386   }
1387   tok = next;
1388   if (!tok) {
1389     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_mda_count");
1390     return -1;
1391   }
1392   p = strchrnul (tok, ',');
1393   if (*p) next = p+1; else next = NULL;
1394   *p = '\0';
1395   if (sscanf (tok, "%"SCNi64, &r->vg_mda_count) != 1) {
1396     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_mda_count");
1397     return -1;
1398   }
1399   tok = next;
1400   if (!tok) {
1401     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_mda_free");
1402     return -1;
1403   }
1404   p = strchrnul (tok, ',');
1405   if (*p) next = p+1; else next = NULL;
1406   *p = '\0';
1407   if (sscanf (tok, "%"SCNu64, &r->vg_mda_free) != 1) {
1408     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_mda_free");
1409     return -1;
1410   }
1411   tok = next;
1412   if (tok != NULL) {
1413     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
1414     return -1;
1415   }
1416   return 0;
1417 }
1418
1419 guestfs_lvm_int_vg_list *
1420 parse_command_line_vgs (void)
1421 {
1422   char *out, *err;
1423   char *p, *pend;
1424   int r, i;
1425   guestfs_lvm_int_vg_list *ret;
1426   void *newp;
1427
1428   ret = malloc (sizeof *ret);
1429   if (!ret) {
1430     reply_with_perror ("malloc");
1431     return NULL;
1432   }
1433
1434   ret->guestfs_lvm_int_vg_list_len = 0;
1435   ret->guestfs_lvm_int_vg_list_val = NULL;
1436
1437   r = command (&out, &err,
1438                "/sbin/lvm", "vgs",
1439                "-o", lvm_vg_cols, "--unbuffered", "--noheadings",
1440                "--nosuffix", "--separator", ",", "--units", "b", NULL);
1441   if (r == -1) {
1442     reply_with_error ("%s", err);
1443     free (out);
1444     free (err);
1445     return NULL;
1446   }
1447
1448   free (err);
1449
1450   /* Tokenize each line of the output. */
1451   p = out;
1452   i = 0;
1453   while (p) {
1454     pend = strchr (p, '\n');    /* Get the next line of output. */
1455     if (pend) {
1456       *pend = '\0';
1457       pend++;
1458     }
1459
1460     while (*p && isspace (*p))  /* Skip any leading whitespace. */
1461       p++;
1462
1463     if (!*p) {                  /* Empty line?  Skip it. */
1464       p = pend;
1465       continue;
1466     }
1467
1468     /* Allocate some space to store this next entry. */
1469     newp = realloc (ret->guestfs_lvm_int_vg_list_val,
1470                     sizeof (guestfs_lvm_int_vg) * (i+1));
1471     if (newp == NULL) {
1472       reply_with_perror ("realloc");
1473       free (ret->guestfs_lvm_int_vg_list_val);
1474       free (ret);
1475       free (out);
1476       return NULL;
1477     }
1478     ret->guestfs_lvm_int_vg_list_val = newp;
1479
1480     /* Tokenize the next entry. */
1481     r = lvm_tokenize_vg (p, &ret->guestfs_lvm_int_vg_list_val[i]);
1482     if (r == -1) {
1483       reply_with_error ("failed to parse output of 'vgs' command");
1484       free (ret->guestfs_lvm_int_vg_list_val);
1485       free (ret);
1486       free (out);
1487       return NULL;
1488     }
1489
1490     ++i;
1491     p = pend;
1492   }
1493
1494   ret->guestfs_lvm_int_vg_list_len = i;
1495
1496   free (out);
1497   return ret;
1498 }
1499 static const char *lvm_lv_cols = "lv_name,lv_uuid,lv_attr,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,lv_size,seg_count,origin,snap_percent,copy_percent,move_pv,lv_tags,mirror_log,modules";
1500
1501 static int lvm_tokenize_lv (char *str, struct guestfs_lvm_int_lv *r)
1502 {
1503   char *tok, *p, *next;
1504   int i, j;
1505
1506   if (!str) {
1507     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
1508     return -1;
1509   }
1510   if (!*str || isspace (*str)) {
1511     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
1512     return -1;
1513   }
1514   tok = str;
1515   if (!tok) {
1516     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_name");
1517     return -1;
1518   }
1519   p = strchrnul (tok, ',');
1520   if (*p) next = p+1; else next = NULL;
1521   *p = '\0';
1522   r->lv_name = strdup (tok);
1523   if (r->lv_name == NULL) {
1524     perror ("strdup");
1525     return -1;
1526   }
1527   tok = next;
1528   if (!tok) {
1529     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_uuid");
1530     return -1;
1531   }
1532   p = strchrnul (tok, ',');
1533   if (*p) next = p+1; else next = NULL;
1534   *p = '\0';
1535   for (i = j = 0; i < 32; ++j) {
1536     if (tok[j] == '\0') {
1537       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
1538       return -1;
1539     } else if (tok[j] != '-')
1540       r->lv_uuid[i++] = tok[j];
1541   }
1542   tok = next;
1543   if (!tok) {
1544     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_attr");
1545     return -1;
1546   }
1547   p = strchrnul (tok, ',');
1548   if (*p) next = p+1; else next = NULL;
1549   *p = '\0';
1550   r->lv_attr = strdup (tok);
1551   if (r->lv_attr == NULL) {
1552     perror ("strdup");
1553     return -1;
1554   }
1555   tok = next;
1556   if (!tok) {
1557     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_major");
1558     return -1;
1559   }
1560   p = strchrnul (tok, ',');
1561   if (*p) next = p+1; else next = NULL;
1562   *p = '\0';
1563   if (sscanf (tok, "%"SCNi64, &r->lv_major) != 1) {
1564     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_major");
1565     return -1;
1566   }
1567   tok = next;
1568   if (!tok) {
1569     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_minor");
1570     return -1;
1571   }
1572   p = strchrnul (tok, ',');
1573   if (*p) next = p+1; else next = NULL;
1574   *p = '\0';
1575   if (sscanf (tok, "%"SCNi64, &r->lv_minor) != 1) {
1576     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_minor");
1577     return -1;
1578   }
1579   tok = next;
1580   if (!tok) {
1581     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_kernel_major");
1582     return -1;
1583   }
1584   p = strchrnul (tok, ',');
1585   if (*p) next = p+1; else next = NULL;
1586   *p = '\0';
1587   if (sscanf (tok, "%"SCNi64, &r->lv_kernel_major) != 1) {
1588     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_kernel_major");
1589     return -1;
1590   }
1591   tok = next;
1592   if (!tok) {
1593     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_kernel_minor");
1594     return -1;
1595   }
1596   p = strchrnul (tok, ',');
1597   if (*p) next = p+1; else next = NULL;
1598   *p = '\0';
1599   if (sscanf (tok, "%"SCNi64, &r->lv_kernel_minor) != 1) {
1600     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_kernel_minor");
1601     return -1;
1602   }
1603   tok = next;
1604   if (!tok) {
1605     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_size");
1606     return -1;
1607   }
1608   p = strchrnul (tok, ',');
1609   if (*p) next = p+1; else next = NULL;
1610   *p = '\0';
1611   if (sscanf (tok, "%"SCNu64, &r->lv_size) != 1) {
1612     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "lv_size");
1613     return -1;
1614   }
1615   tok = next;
1616   if (!tok) {
1617     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "seg_count");
1618     return -1;
1619   }
1620   p = strchrnul (tok, ',');
1621   if (*p) next = p+1; else next = NULL;
1622   *p = '\0';
1623   if (sscanf (tok, "%"SCNi64, &r->seg_count) != 1) {
1624     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "seg_count");
1625     return -1;
1626   }
1627   tok = next;
1628   if (!tok) {
1629     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "origin");
1630     return -1;
1631   }
1632   p = strchrnul (tok, ',');
1633   if (*p) next = p+1; else next = NULL;
1634   *p = '\0';
1635   r->origin = strdup (tok);
1636   if (r->origin == NULL) {
1637     perror ("strdup");
1638     return -1;
1639   }
1640   tok = next;
1641   if (!tok) {
1642     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "snap_percent");
1643     return -1;
1644   }
1645   p = strchrnul (tok, ',');
1646   if (*p) next = p+1; else next = NULL;
1647   *p = '\0';
1648   if (tok[0] == '\0')
1649     r->snap_percent = -1;
1650   else if (sscanf (tok, "%f", &r->snap_percent) != 1) {
1651     fprintf (stderr, "%s: failed to parse float '%s' from token %s\n", __func__, tok, "snap_percent");
1652     return -1;
1653   }
1654   tok = next;
1655   if (!tok) {
1656     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "copy_percent");
1657     return -1;
1658   }
1659   p = strchrnul (tok, ',');
1660   if (*p) next = p+1; else next = NULL;
1661   *p = '\0';
1662   if (tok[0] == '\0')
1663     r->copy_percent = -1;
1664   else if (sscanf (tok, "%f", &r->copy_percent) != 1) {
1665     fprintf (stderr, "%s: failed to parse float '%s' from token %s\n", __func__, tok, "copy_percent");
1666     return -1;
1667   }
1668   tok = next;
1669   if (!tok) {
1670     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "move_pv");
1671     return -1;
1672   }
1673   p = strchrnul (tok, ',');
1674   if (*p) next = p+1; else next = NULL;
1675   *p = '\0';
1676   r->move_pv = strdup (tok);
1677   if (r->move_pv == NULL) {
1678     perror ("strdup");
1679     return -1;
1680   }
1681   tok = next;
1682   if (!tok) {
1683     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_tags");
1684     return -1;
1685   }
1686   p = strchrnul (tok, ',');
1687   if (*p) next = p+1; else next = NULL;
1688   *p = '\0';
1689   r->lv_tags = strdup (tok);
1690   if (r->lv_tags == NULL) {
1691     perror ("strdup");
1692     return -1;
1693   }
1694   tok = next;
1695   if (!tok) {
1696     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "mirror_log");
1697     return -1;
1698   }
1699   p = strchrnul (tok, ',');
1700   if (*p) next = p+1; else next = NULL;
1701   *p = '\0';
1702   r->mirror_log = strdup (tok);
1703   if (r->mirror_log == NULL) {
1704     perror ("strdup");
1705     return -1;
1706   }
1707   tok = next;
1708   if (!tok) {
1709     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "modules");
1710     return -1;
1711   }
1712   p = strchrnul (tok, ',');
1713   if (*p) next = p+1; else next = NULL;
1714   *p = '\0';
1715   r->modules = strdup (tok);
1716   if (r->modules == NULL) {
1717     perror ("strdup");
1718     return -1;
1719   }
1720   tok = next;
1721   if (tok != NULL) {
1722     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
1723     return -1;
1724   }
1725   return 0;
1726 }
1727
1728 guestfs_lvm_int_lv_list *
1729 parse_command_line_lvs (void)
1730 {
1731   char *out, *err;
1732   char *p, *pend;
1733   int r, i;
1734   guestfs_lvm_int_lv_list *ret;
1735   void *newp;
1736
1737   ret = malloc (sizeof *ret);
1738   if (!ret) {
1739     reply_with_perror ("malloc");
1740     return NULL;
1741   }
1742
1743   ret->guestfs_lvm_int_lv_list_len = 0;
1744   ret->guestfs_lvm_int_lv_list_val = NULL;
1745
1746   r = command (&out, &err,
1747                "/sbin/lvm", "lvs",
1748                "-o", lvm_lv_cols, "--unbuffered", "--noheadings",
1749                "--nosuffix", "--separator", ",", "--units", "b", NULL);
1750   if (r == -1) {
1751     reply_with_error ("%s", err);
1752     free (out);
1753     free (err);
1754     return NULL;
1755   }
1756
1757   free (err);
1758
1759   /* Tokenize each line of the output. */
1760   p = out;
1761   i = 0;
1762   while (p) {
1763     pend = strchr (p, '\n');    /* Get the next line of output. */
1764     if (pend) {
1765       *pend = '\0';
1766       pend++;
1767     }
1768
1769     while (*p && isspace (*p))  /* Skip any leading whitespace. */
1770       p++;
1771
1772     if (!*p) {                  /* Empty line?  Skip it. */
1773       p = pend;
1774       continue;
1775     }
1776
1777     /* Allocate some space to store this next entry. */
1778     newp = realloc (ret->guestfs_lvm_int_lv_list_val,
1779                     sizeof (guestfs_lvm_int_lv) * (i+1));
1780     if (newp == NULL) {
1781       reply_with_perror ("realloc");
1782       free (ret->guestfs_lvm_int_lv_list_val);
1783       free (ret);
1784       free (out);
1785       return NULL;
1786     }
1787     ret->guestfs_lvm_int_lv_list_val = newp;
1788
1789     /* Tokenize the next entry. */
1790     r = lvm_tokenize_lv (p, &ret->guestfs_lvm_int_lv_list_val[i]);
1791     if (r == -1) {
1792       reply_with_error ("failed to parse output of 'lvs' command");
1793       free (ret->guestfs_lvm_int_lv_list_val);
1794       free (ret);
1795       free (out);
1796       return NULL;
1797     }
1798
1799     ++i;
1800     p = pend;
1801   }
1802
1803   ret->guestfs_lvm_int_lv_list_len = i;
1804
1805   free (out);
1806   return ret;
1807 }