63ca7704eb3ad2254128fe9c5b4b2a3d91454a81
[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 ("mount: daemon failed to decode procedure arguments");
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 ("touch: daemon failed to decode procedure arguments");
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 ("cat: daemon failed to decode procedure arguments");
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 ("ll: daemon failed to decode procedure arguments");
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 ("ls: daemon failed to decode procedure arguments");
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_full_stub (XDR *xdr_in)
203 {
204   guestfs_lvm_int_pv_list *r;
205
206   r = do_pvs_full ();
207   if (r == NULL)
208     /* do_pvs_full has already called reply_with_error, so just return */
209     return;
210
211   struct guestfs_pvs_full_ret ret;
212   ret.physvols = *r;
213   reply ((xdrproc_t) &xdr_guestfs_pvs_full_ret, (char *) &ret);
214   xdr_free ((xdrproc_t) xdr_guestfs_pvs_full_ret, (char *) &ret);
215 }
216
217 static void vgs_full_stub (XDR *xdr_in)
218 {
219   guestfs_lvm_int_vg_list *r;
220
221   r = do_vgs_full ();
222   if (r == NULL)
223     /* do_vgs_full has already called reply_with_error, so just return */
224     return;
225
226   struct guestfs_vgs_full_ret ret;
227   ret.volgroups = *r;
228   reply ((xdrproc_t) &xdr_guestfs_vgs_full_ret, (char *) &ret);
229   xdr_free ((xdrproc_t) xdr_guestfs_vgs_full_ret, (char *) &ret);
230 }
231
232 static void lvs_full_stub (XDR *xdr_in)
233 {
234   guestfs_lvm_int_lv_list *r;
235
236   r = do_lvs_full ();
237   if (r == NULL)
238     /* do_lvs_full has already called reply_with_error, so just return */
239     return;
240
241   struct guestfs_lvs_full_ret ret;
242   ret.logvols = *r;
243   reply ((xdrproc_t) &xdr_guestfs_lvs_full_ret, (char *) &ret);
244   xdr_free ((xdrproc_t) xdr_guestfs_lvs_full_ret, (char *) &ret);
245 }
246
247 void dispatch_incoming_message (XDR *xdr_in)
248 {
249   switch (proc_nr) {
250     case GUESTFS_PROC_MOUNT:
251       mount_stub (xdr_in);
252       break;
253     case GUESTFS_PROC_SYNC:
254       sync_stub (xdr_in);
255       break;
256     case GUESTFS_PROC_TOUCH:
257       touch_stub (xdr_in);
258       break;
259     case GUESTFS_PROC_CAT:
260       cat_stub (xdr_in);
261       break;
262     case GUESTFS_PROC_LL:
263       ll_stub (xdr_in);
264       break;
265     case GUESTFS_PROC_LS:
266       ls_stub (xdr_in);
267       break;
268     case GUESTFS_PROC_LIST_DEVICES:
269       list_devices_stub (xdr_in);
270       break;
271     case GUESTFS_PROC_LIST_PARTITIONS:
272       list_partitions_stub (xdr_in);
273       break;
274     case GUESTFS_PROC_PVS_FULL:
275       pvs_full_stub (xdr_in);
276       break;
277     case GUESTFS_PROC_VGS_FULL:
278       vgs_full_stub (xdr_in);
279       break;
280     case GUESTFS_PROC_LVS_FULL:
281       lvs_full_stub (xdr_in);
282       break;
283     default:
284       reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
285   }
286 }
287
288 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";
289
290 static int lvm_tokenize_pv (char *str, struct guestfs_lvm_int_pv *r)
291 {
292   char *tok, *p, *next;
293   int i, j;
294
295   if (!str) {
296     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
297     return -1;
298   }
299   if (!*str || isspace (*str)) {
300     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
301     return -1;
302   }
303   tok = str;
304   if (!tok) {
305     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_name");
306     return -1;
307   }
308   p = strchrnul (tok, ',');
309   if (*p) next = p+1; else next = NULL;
310   *p = '\0';
311   r->pv_name = strdup (tok);
312   if (r->pv_name == NULL) {
313     perror ("strdup");
314     return -1;
315   }
316   tok = next;
317   if (!tok) {
318     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_uuid");
319     return -1;
320   }
321   p = strchrnul (tok, ',');
322   if (*p) next = p+1; else next = NULL;
323   *p = '\0';
324   for (i = j = 0; i < 32; ++j) {
325     if (tok[j] == '\0') {
326       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
327       return -1;
328     } else if (tok[j] != '-')
329       r->pv_uuid[i++] = tok[j];
330   }
331   tok = next;
332   if (!tok) {
333     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_fmt");
334     return -1;
335   }
336   p = strchrnul (tok, ',');
337   if (*p) next = p+1; else next = NULL;
338   *p = '\0';
339   r->pv_fmt = strdup (tok);
340   if (r->pv_fmt == NULL) {
341     perror ("strdup");
342     return -1;
343   }
344   tok = next;
345   if (!tok) {
346     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_size");
347     return -1;
348   }
349   p = strchrnul (tok, ',');
350   if (*p) next = p+1; else next = NULL;
351   *p = '\0';
352   if (sscanf (tok, "%"SCNu64, &r->pv_size) != 1) {
353     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_size");
354     return -1;
355   }
356   tok = next;
357   if (!tok) {
358     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "dev_size");
359     return -1;
360   }
361   p = strchrnul (tok, ',');
362   if (*p) next = p+1; else next = NULL;
363   *p = '\0';
364   if (sscanf (tok, "%"SCNu64, &r->dev_size) != 1) {
365     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "dev_size");
366     return -1;
367   }
368   tok = next;
369   if (!tok) {
370     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_free");
371     return -1;
372   }
373   p = strchrnul (tok, ',');
374   if (*p) next = p+1; else next = NULL;
375   *p = '\0';
376   if (sscanf (tok, "%"SCNu64, &r->pv_free) != 1) {
377     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_free");
378     return -1;
379   }
380   tok = next;
381   if (!tok) {
382     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_used");
383     return -1;
384   }
385   p = strchrnul (tok, ',');
386   if (*p) next = p+1; else next = NULL;
387   *p = '\0';
388   if (sscanf (tok, "%"SCNu64, &r->pv_used) != 1) {
389     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_used");
390     return -1;
391   }
392   tok = next;
393   if (!tok) {
394     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_attr");
395     return -1;
396   }
397   p = strchrnul (tok, ',');
398   if (*p) next = p+1; else next = NULL;
399   *p = '\0';
400   r->pv_attr = strdup (tok);
401   if (r->pv_attr == NULL) {
402     perror ("strdup");
403     return -1;
404   }
405   tok = next;
406   if (!tok) {
407     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_pe_count");
408     return -1;
409   }
410   p = strchrnul (tok, ',');
411   if (*p) next = p+1; else next = NULL;
412   *p = '\0';
413   if (sscanf (tok, "%"SCNi64, &r->pv_pe_count) != 1) {
414     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_pe_count");
415     return -1;
416   }
417   tok = next;
418   if (!tok) {
419     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_pe_alloc_count");
420     return -1;
421   }
422   p = strchrnul (tok, ',');
423   if (*p) next = p+1; else next = NULL;
424   *p = '\0';
425   if (sscanf (tok, "%"SCNi64, &r->pv_pe_alloc_count) != 1) {
426     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_pe_alloc_count");
427     return -1;
428   }
429   tok = next;
430   if (!tok) {
431     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_tags");
432     return -1;
433   }
434   p = strchrnul (tok, ',');
435   if (*p) next = p+1; else next = NULL;
436   *p = '\0';
437   r->pv_tags = strdup (tok);
438   if (r->pv_tags == NULL) {
439     perror ("strdup");
440     return -1;
441   }
442   tok = next;
443   if (!tok) {
444     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pe_start");
445     return -1;
446   }
447   p = strchrnul (tok, ',');
448   if (*p) next = p+1; else next = NULL;
449   *p = '\0';
450   if (sscanf (tok, "%"SCNu64, &r->pe_start) != 1) {
451     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pe_start");
452     return -1;
453   }
454   tok = next;
455   if (!tok) {
456     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_mda_count");
457     return -1;
458   }
459   p = strchrnul (tok, ',');
460   if (*p) next = p+1; else next = NULL;
461   *p = '\0';
462   if (sscanf (tok, "%"SCNi64, &r->pv_mda_count) != 1) {
463     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_mda_count");
464     return -1;
465   }
466   tok = next;
467   if (!tok) {
468     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_mda_free");
469     return -1;
470   }
471   p = strchrnul (tok, ',');
472   if (*p) next = p+1; else next = NULL;
473   *p = '\0';
474   if (sscanf (tok, "%"SCNu64, &r->pv_mda_free) != 1) {
475     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "pv_mda_free");
476     return -1;
477   }
478   tok = next;
479   if (tok != NULL) {
480     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
481     return -1;
482   }
483   return 0;
484 }
485
486 guestfs_lvm_int_pv_list *
487 parse_command_line_pvs (void)
488 {
489   char *out, *err;
490   char *p, *pend;
491   int r, i;
492   guestfs_lvm_int_pv_list *ret;
493   void *newp;
494
495   ret = malloc (sizeof *ret);
496   if (!ret) {
497     reply_with_perror ("malloc");
498     return NULL;
499   }
500
501   ret->guestfs_lvm_int_pv_list_len = 0;
502   ret->guestfs_lvm_int_pv_list_val = NULL;
503
504   r = command (&out, &err,
505                "/sbin/lvm", "pvs",
506                "-o", lvm_pv_cols, "--unbuffered", "--noheadings",
507                "--nosuffix", "--separator", ",", "--units", "b", NULL);
508   if (r == -1) {
509     reply_with_error ("%s", err);
510     free (out);
511     free (err);
512     return NULL;
513   }
514
515   free (err);
516
517   /* Tokenize each line of the output. */
518   p = out;
519   i = 0;
520   while (p) {
521     pend = strchr (p, '\n');    /* Get the next line of output. */
522     if (pend) {
523       *pend = '\0';
524       pend++;
525     }
526
527     while (*p && isspace (*p))  /* Skip any leading whitespace. */
528       p++;
529
530     if (!*p) {                  /* Empty line?  Skip it. */
531       p = pend;
532       continue;
533     }
534
535     /* Allocate some space to store this next entry. */
536     newp = realloc (ret->guestfs_lvm_int_pv_list_val,
537                     sizeof (guestfs_lvm_int_pv) * (i+1));
538     if (newp == NULL) {
539       reply_with_perror ("realloc");
540       free (ret->guestfs_lvm_int_pv_list_val);
541       free (ret);
542       free (out);
543       return NULL;
544     }
545     ret->guestfs_lvm_int_pv_list_val = newp;
546
547     /* Tokenize the next entry. */
548     r = lvm_tokenize_pv (p, &ret->guestfs_lvm_int_pv_list_val[i]);
549     if (r == -1) {
550       reply_with_error ("failed to parse output of 'pvs' command");
551       free (ret->guestfs_lvm_int_pv_list_val);
552       free (ret);
553       free (out);
554       return NULL;
555     }
556
557     ++i;
558     p = pend;
559   }
560
561   ret->guestfs_lvm_int_pv_list_len = i;
562
563   free (out);
564   return ret;
565 }
566 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";
567
568 static int lvm_tokenize_vg (char *str, struct guestfs_lvm_int_vg *r)
569 {
570   char *tok, *p, *next;
571   int i, j;
572
573   if (!str) {
574     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
575     return -1;
576   }
577   if (!*str || isspace (*str)) {
578     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
579     return -1;
580   }
581   tok = str;
582   if (!tok) {
583     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_name");
584     return -1;
585   }
586   p = strchrnul (tok, ',');
587   if (*p) next = p+1; else next = NULL;
588   *p = '\0';
589   r->vg_name = strdup (tok);
590   if (r->vg_name == NULL) {
591     perror ("strdup");
592     return -1;
593   }
594   tok = next;
595   if (!tok) {
596     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_uuid");
597     return -1;
598   }
599   p = strchrnul (tok, ',');
600   if (*p) next = p+1; else next = NULL;
601   *p = '\0';
602   for (i = j = 0; i < 32; ++j) {
603     if (tok[j] == '\0') {
604       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
605       return -1;
606     } else if (tok[j] != '-')
607       r->vg_uuid[i++] = tok[j];
608   }
609   tok = next;
610   if (!tok) {
611     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_fmt");
612     return -1;
613   }
614   p = strchrnul (tok, ',');
615   if (*p) next = p+1; else next = NULL;
616   *p = '\0';
617   r->vg_fmt = strdup (tok);
618   if (r->vg_fmt == NULL) {
619     perror ("strdup");
620     return -1;
621   }
622   tok = next;
623   if (!tok) {
624     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_attr");
625     return -1;
626   }
627   p = strchrnul (tok, ',');
628   if (*p) next = p+1; else next = NULL;
629   *p = '\0';
630   r->vg_attr = strdup (tok);
631   if (r->vg_attr == NULL) {
632     perror ("strdup");
633     return -1;
634   }
635   tok = next;
636   if (!tok) {
637     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_size");
638     return -1;
639   }
640   p = strchrnul (tok, ',');
641   if (*p) next = p+1; else next = NULL;
642   *p = '\0';
643   if (sscanf (tok, "%"SCNu64, &r->vg_size) != 1) {
644     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_size");
645     return -1;
646   }
647   tok = next;
648   if (!tok) {
649     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_free");
650     return -1;
651   }
652   p = strchrnul (tok, ',');
653   if (*p) next = p+1; else next = NULL;
654   *p = '\0';
655   if (sscanf (tok, "%"SCNu64, &r->vg_free) != 1) {
656     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_free");
657     return -1;
658   }
659   tok = next;
660   if (!tok) {
661     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_sysid");
662     return -1;
663   }
664   p = strchrnul (tok, ',');
665   if (*p) next = p+1; else next = NULL;
666   *p = '\0';
667   r->vg_sysid = strdup (tok);
668   if (r->vg_sysid == NULL) {
669     perror ("strdup");
670     return -1;
671   }
672   tok = next;
673   if (!tok) {
674     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_extent_size");
675     return -1;
676   }
677   p = strchrnul (tok, ',');
678   if (*p) next = p+1; else next = NULL;
679   *p = '\0';
680   if (sscanf (tok, "%"SCNu64, &r->vg_extent_size) != 1) {
681     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_extent_size");
682     return -1;
683   }
684   tok = next;
685   if (!tok) {
686     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_extent_count");
687     return -1;
688   }
689   p = strchrnul (tok, ',');
690   if (*p) next = p+1; else next = NULL;
691   *p = '\0';
692   if (sscanf (tok, "%"SCNi64, &r->vg_extent_count) != 1) {
693     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_extent_count");
694     return -1;
695   }
696   tok = next;
697   if (!tok) {
698     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_free_count");
699     return -1;
700   }
701   p = strchrnul (tok, ',');
702   if (*p) next = p+1; else next = NULL;
703   *p = '\0';
704   if (sscanf (tok, "%"SCNi64, &r->vg_free_count) != 1) {
705     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_free_count");
706     return -1;
707   }
708   tok = next;
709   if (!tok) {
710     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "max_lv");
711     return -1;
712   }
713   p = strchrnul (tok, ',');
714   if (*p) next = p+1; else next = NULL;
715   *p = '\0';
716   if (sscanf (tok, "%"SCNi64, &r->max_lv) != 1) {
717     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "max_lv");
718     return -1;
719   }
720   tok = next;
721   if (!tok) {
722     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "max_pv");
723     return -1;
724   }
725   p = strchrnul (tok, ',');
726   if (*p) next = p+1; else next = NULL;
727   *p = '\0';
728   if (sscanf (tok, "%"SCNi64, &r->max_pv) != 1) {
729     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "max_pv");
730     return -1;
731   }
732   tok = next;
733   if (!tok) {
734     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "pv_count");
735     return -1;
736   }
737   p = strchrnul (tok, ',');
738   if (*p) next = p+1; else next = NULL;
739   *p = '\0';
740   if (sscanf (tok, "%"SCNi64, &r->pv_count) != 1) {
741     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "pv_count");
742     return -1;
743   }
744   tok = next;
745   if (!tok) {
746     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_count");
747     return -1;
748   }
749   p = strchrnul (tok, ',');
750   if (*p) next = p+1; else next = NULL;
751   *p = '\0';
752   if (sscanf (tok, "%"SCNi64, &r->lv_count) != 1) {
753     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_count");
754     return -1;
755   }
756   tok = next;
757   if (!tok) {
758     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "snap_count");
759     return -1;
760   }
761   p = strchrnul (tok, ',');
762   if (*p) next = p+1; else next = NULL;
763   *p = '\0';
764   if (sscanf (tok, "%"SCNi64, &r->snap_count) != 1) {
765     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "snap_count");
766     return -1;
767   }
768   tok = next;
769   if (!tok) {
770     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_seqno");
771     return -1;
772   }
773   p = strchrnul (tok, ',');
774   if (*p) next = p+1; else next = NULL;
775   *p = '\0';
776   if (sscanf (tok, "%"SCNi64, &r->vg_seqno) != 1) {
777     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_seqno");
778     return -1;
779   }
780   tok = next;
781   if (!tok) {
782     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_tags");
783     return -1;
784   }
785   p = strchrnul (tok, ',');
786   if (*p) next = p+1; else next = NULL;
787   *p = '\0';
788   r->vg_tags = strdup (tok);
789   if (r->vg_tags == NULL) {
790     perror ("strdup");
791     return -1;
792   }
793   tok = next;
794   if (!tok) {
795     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_mda_count");
796     return -1;
797   }
798   p = strchrnul (tok, ',');
799   if (*p) next = p+1; else next = NULL;
800   *p = '\0';
801   if (sscanf (tok, "%"SCNi64, &r->vg_mda_count) != 1) {
802     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "vg_mda_count");
803     return -1;
804   }
805   tok = next;
806   if (!tok) {
807     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "vg_mda_free");
808     return -1;
809   }
810   p = strchrnul (tok, ',');
811   if (*p) next = p+1; else next = NULL;
812   *p = '\0';
813   if (sscanf (tok, "%"SCNu64, &r->vg_mda_free) != 1) {
814     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "vg_mda_free");
815     return -1;
816   }
817   tok = next;
818   if (tok != NULL) {
819     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
820     return -1;
821   }
822   return 0;
823 }
824
825 guestfs_lvm_int_vg_list *
826 parse_command_line_vgs (void)
827 {
828   char *out, *err;
829   char *p, *pend;
830   int r, i;
831   guestfs_lvm_int_vg_list *ret;
832   void *newp;
833
834   ret = malloc (sizeof *ret);
835   if (!ret) {
836     reply_with_perror ("malloc");
837     return NULL;
838   }
839
840   ret->guestfs_lvm_int_vg_list_len = 0;
841   ret->guestfs_lvm_int_vg_list_val = NULL;
842
843   r = command (&out, &err,
844                "/sbin/lvm", "vgs",
845                "-o", lvm_vg_cols, "--unbuffered", "--noheadings",
846                "--nosuffix", "--separator", ",", "--units", "b", NULL);
847   if (r == -1) {
848     reply_with_error ("%s", err);
849     free (out);
850     free (err);
851     return NULL;
852   }
853
854   free (err);
855
856   /* Tokenize each line of the output. */
857   p = out;
858   i = 0;
859   while (p) {
860     pend = strchr (p, '\n');    /* Get the next line of output. */
861     if (pend) {
862       *pend = '\0';
863       pend++;
864     }
865
866     while (*p && isspace (*p))  /* Skip any leading whitespace. */
867       p++;
868
869     if (!*p) {                  /* Empty line?  Skip it. */
870       p = pend;
871       continue;
872     }
873
874     /* Allocate some space to store this next entry. */
875     newp = realloc (ret->guestfs_lvm_int_vg_list_val,
876                     sizeof (guestfs_lvm_int_vg) * (i+1));
877     if (newp == NULL) {
878       reply_with_perror ("realloc");
879       free (ret->guestfs_lvm_int_vg_list_val);
880       free (ret);
881       free (out);
882       return NULL;
883     }
884     ret->guestfs_lvm_int_vg_list_val = newp;
885
886     /* Tokenize the next entry. */
887     r = lvm_tokenize_vg (p, &ret->guestfs_lvm_int_vg_list_val[i]);
888     if (r == -1) {
889       reply_with_error ("failed to parse output of 'vgs' command");
890       free (ret->guestfs_lvm_int_vg_list_val);
891       free (ret);
892       free (out);
893       return NULL;
894     }
895
896     ++i;
897     p = pend;
898   }
899
900   ret->guestfs_lvm_int_vg_list_len = i;
901
902   free (out);
903   return ret;
904 }
905 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";
906
907 static int lvm_tokenize_lv (char *str, struct guestfs_lvm_int_lv *r)
908 {
909   char *tok, *p, *next;
910   int i, j;
911
912   if (!str) {
913     fprintf (stderr, "%s: failed: passed a NULL string\n", __func__);
914     return -1;
915   }
916   if (!*str || isspace (*str)) {
917     fprintf (stderr, "%s: failed: passed a empty string or one beginning with whitespace\n", __func__);
918     return -1;
919   }
920   tok = str;
921   if (!tok) {
922     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_name");
923     return -1;
924   }
925   p = strchrnul (tok, ',');
926   if (*p) next = p+1; else next = NULL;
927   *p = '\0';
928   r->lv_name = strdup (tok);
929   if (r->lv_name == NULL) {
930     perror ("strdup");
931     return -1;
932   }
933   tok = next;
934   if (!tok) {
935     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_uuid");
936     return -1;
937   }
938   p = strchrnul (tok, ',');
939   if (*p) next = p+1; else next = NULL;
940   *p = '\0';
941   for (i = j = 0; i < 32; ++j) {
942     if (tok[j] == '\0') {
943       fprintf (stderr, "%s: failed to parse UUID from '%s'\n", __func__, tok);
944       return -1;
945     } else if (tok[j] != '-')
946       r->lv_uuid[i++] = tok[j];
947   }
948   tok = next;
949   if (!tok) {
950     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_attr");
951     return -1;
952   }
953   p = strchrnul (tok, ',');
954   if (*p) next = p+1; else next = NULL;
955   *p = '\0';
956   r->lv_attr = strdup (tok);
957   if (r->lv_attr == NULL) {
958     perror ("strdup");
959     return -1;
960   }
961   tok = next;
962   if (!tok) {
963     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_major");
964     return -1;
965   }
966   p = strchrnul (tok, ',');
967   if (*p) next = p+1; else next = NULL;
968   *p = '\0';
969   if (sscanf (tok, "%"SCNi64, &r->lv_major) != 1) {
970     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_major");
971     return -1;
972   }
973   tok = next;
974   if (!tok) {
975     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_minor");
976     return -1;
977   }
978   p = strchrnul (tok, ',');
979   if (*p) next = p+1; else next = NULL;
980   *p = '\0';
981   if (sscanf (tok, "%"SCNi64, &r->lv_minor) != 1) {
982     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_minor");
983     return -1;
984   }
985   tok = next;
986   if (!tok) {
987     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_kernel_major");
988     return -1;
989   }
990   p = strchrnul (tok, ',');
991   if (*p) next = p+1; else next = NULL;
992   *p = '\0';
993   if (sscanf (tok, "%"SCNi64, &r->lv_kernel_major) != 1) {
994     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_kernel_major");
995     return -1;
996   }
997   tok = next;
998   if (!tok) {
999     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_kernel_minor");
1000     return -1;
1001   }
1002   p = strchrnul (tok, ',');
1003   if (*p) next = p+1; else next = NULL;
1004   *p = '\0';
1005   if (sscanf (tok, "%"SCNi64, &r->lv_kernel_minor) != 1) {
1006     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "lv_kernel_minor");
1007     return -1;
1008   }
1009   tok = next;
1010   if (!tok) {
1011     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_size");
1012     return -1;
1013   }
1014   p = strchrnul (tok, ',');
1015   if (*p) next = p+1; else next = NULL;
1016   *p = '\0';
1017   if (sscanf (tok, "%"SCNu64, &r->lv_size) != 1) {
1018     fprintf (stderr, "%s: failed to parse size '%s' from token %s\n", __func__, tok, "lv_size");
1019     return -1;
1020   }
1021   tok = next;
1022   if (!tok) {
1023     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "seg_count");
1024     return -1;
1025   }
1026   p = strchrnul (tok, ',');
1027   if (*p) next = p+1; else next = NULL;
1028   *p = '\0';
1029   if (sscanf (tok, "%"SCNi64, &r->seg_count) != 1) {
1030     fprintf (stderr, "%s: failed to parse int '%s' from token %s\n", __func__, tok, "seg_count");
1031     return -1;
1032   }
1033   tok = next;
1034   if (!tok) {
1035     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "origin");
1036     return -1;
1037   }
1038   p = strchrnul (tok, ',');
1039   if (*p) next = p+1; else next = NULL;
1040   *p = '\0';
1041   r->origin = strdup (tok);
1042   if (r->origin == NULL) {
1043     perror ("strdup");
1044     return -1;
1045   }
1046   tok = next;
1047   if (!tok) {
1048     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "snap_percent");
1049     return -1;
1050   }
1051   p = strchrnul (tok, ',');
1052   if (*p) next = p+1; else next = NULL;
1053   *p = '\0';
1054   if (tok[0] == '\0')
1055     r->snap_percent = -1;
1056   else if (sscanf (tok, "%f", &r->snap_percent) != 1) {
1057     fprintf (stderr, "%s: failed to parse float '%s' from token %s\n", __func__, tok, "snap_percent");
1058     return -1;
1059   }
1060   tok = next;
1061   if (!tok) {
1062     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "copy_percent");
1063     return -1;
1064   }
1065   p = strchrnul (tok, ',');
1066   if (*p) next = p+1; else next = NULL;
1067   *p = '\0';
1068   if (tok[0] == '\0')
1069     r->copy_percent = -1;
1070   else if (sscanf (tok, "%f", &r->copy_percent) != 1) {
1071     fprintf (stderr, "%s: failed to parse float '%s' from token %s\n", __func__, tok, "copy_percent");
1072     return -1;
1073   }
1074   tok = next;
1075   if (!tok) {
1076     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "move_pv");
1077     return -1;
1078   }
1079   p = strchrnul (tok, ',');
1080   if (*p) next = p+1; else next = NULL;
1081   *p = '\0';
1082   r->move_pv = strdup (tok);
1083   if (r->move_pv == NULL) {
1084     perror ("strdup");
1085     return -1;
1086   }
1087   tok = next;
1088   if (!tok) {
1089     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "lv_tags");
1090     return -1;
1091   }
1092   p = strchrnul (tok, ',');
1093   if (*p) next = p+1; else next = NULL;
1094   *p = '\0';
1095   r->lv_tags = strdup (tok);
1096   if (r->lv_tags == NULL) {
1097     perror ("strdup");
1098     return -1;
1099   }
1100   tok = next;
1101   if (!tok) {
1102     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "mirror_log");
1103     return -1;
1104   }
1105   p = strchrnul (tok, ',');
1106   if (*p) next = p+1; else next = NULL;
1107   *p = '\0';
1108   r->mirror_log = strdup (tok);
1109   if (r->mirror_log == NULL) {
1110     perror ("strdup");
1111     return -1;
1112   }
1113   tok = next;
1114   if (!tok) {
1115     fprintf (stderr, "%s: failed: string finished early, around token %s\n", __func__, "modules");
1116     return -1;
1117   }
1118   p = strchrnul (tok, ',');
1119   if (*p) next = p+1; else next = NULL;
1120   *p = '\0';
1121   r->modules = strdup (tok);
1122   if (r->modules == NULL) {
1123     perror ("strdup");
1124     return -1;
1125   }
1126   tok = next;
1127   if (tok != NULL) {
1128     fprintf (stderr, "%s: failed: extra tokens at end of string\n", __func__);
1129     return -1;
1130   }
1131   return 0;
1132 }
1133
1134 guestfs_lvm_int_lv_list *
1135 parse_command_line_lvs (void)
1136 {
1137   char *out, *err;
1138   char *p, *pend;
1139   int r, i;
1140   guestfs_lvm_int_lv_list *ret;
1141   void *newp;
1142
1143   ret = malloc (sizeof *ret);
1144   if (!ret) {
1145     reply_with_perror ("malloc");
1146     return NULL;
1147   }
1148
1149   ret->guestfs_lvm_int_lv_list_len = 0;
1150   ret->guestfs_lvm_int_lv_list_val = NULL;
1151
1152   r = command (&out, &err,
1153                "/sbin/lvm", "lvs",
1154                "-o", lvm_lv_cols, "--unbuffered", "--noheadings",
1155                "--nosuffix", "--separator", ",", "--units", "b", NULL);
1156   if (r == -1) {
1157     reply_with_error ("%s", err);
1158     free (out);
1159     free (err);
1160     return NULL;
1161   }
1162
1163   free (err);
1164
1165   /* Tokenize each line of the output. */
1166   p = out;
1167   i = 0;
1168   while (p) {
1169     pend = strchr (p, '\n');    /* Get the next line of output. */
1170     if (pend) {
1171       *pend = '\0';
1172       pend++;
1173     }
1174
1175     while (*p && isspace (*p))  /* Skip any leading whitespace. */
1176       p++;
1177
1178     if (!*p) {                  /* Empty line?  Skip it. */
1179       p = pend;
1180       continue;
1181     }
1182
1183     /* Allocate some space to store this next entry. */
1184     newp = realloc (ret->guestfs_lvm_int_lv_list_val,
1185                     sizeof (guestfs_lvm_int_lv) * (i+1));
1186     if (newp == NULL) {
1187       reply_with_perror ("realloc");
1188       free (ret->guestfs_lvm_int_lv_list_val);
1189       free (ret);
1190       free (out);
1191       return NULL;
1192     }
1193     ret->guestfs_lvm_int_lv_list_val = newp;
1194
1195     /* Tokenize the next entry. */
1196     r = lvm_tokenize_lv (p, &ret->guestfs_lvm_int_lv_list_val[i]);
1197     if (r == -1) {
1198       reply_with_error ("failed to parse output of 'lvs' command");
1199       free (ret->guestfs_lvm_int_lv_list_val);
1200       free (ret);
1201       free (out);
1202       return NULL;
1203     }
1204
1205     ++i;
1206     p = pend;
1207   }
1208
1209   ret->guestfs_lvm_int_lv_list_len = i;
1210
1211   free (out);
1212   return ret;
1213 }