Implement simple lvs/vgs/pvs commands.
[libguestfs.git] / daemon / lvm.c
1 /* libguestfs - the guestfsd daemon
2  * Copyright (C) 2009 Red Hat Inc. 
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <ctype.h>
26
27 #include "daemon.h"
28 #include "actions.h"
29
30 /* LVM actions.  Keep an eye on liblvm, although at the time
31  * of writing it hasn't progressed very far.
32  */
33
34 static char **
35 convert_lvm_output (char *out, char *prefix)
36 {
37   char *p, *pend;
38   char **r = NULL;
39   int size = 0, alloc = 0;
40   char buf[256];
41   char *str;
42
43   p = out;
44   while (p) {
45     pend = strchr (p, '\n');    /* Get the next line of output. */
46     if (pend) {
47       *pend = '\0';
48       pend++;
49     }
50
51     while (*p && isspace (*p))  /* Skip any leading whitespace. */
52       p++;
53
54     if (!*p) {                  /* Empty line?  Skip it. */
55       p = pend;
56       continue;
57     }
58
59     /* Prefix? */
60     if (prefix) {
61       snprintf (buf, sizeof buf, "%s%s", prefix, p);
62       str = buf;
63     } else
64       str = p;
65
66     if (add_string (&r, &size, &alloc, str) == -1) {
67       free (out);
68       return NULL;
69     }
70
71     p = pend;
72   }
73
74   free (out);
75
76   if (add_string (&r, &size, &alloc, NULL) == -1)
77     return NULL;
78
79   sort_strings (r, size-1);
80   return r;
81 }
82
83 char **
84 do_pvs (void)
85 {
86   char *out, *err;
87   int r;
88
89   r = command (&out, &err,
90                "/sbin/lvm", "pvs", "-o", "pv_name", "--noheadings", NULL);
91   if (r == -1) {
92     reply_with_error ("%s", err);
93     free (out);
94     free (err);
95     return NULL;
96   }
97
98   free (err);
99
100   return convert_lvm_output (out, NULL);
101 }
102
103 char **
104 do_vgs (void)
105 {
106   char *out, *err;
107   int r;
108
109   r = command (&out, &err,
110                "/sbin/lvm", "vgs", "-o", "vg_name", "--noheadings", NULL);
111   if (r == -1) {
112     reply_with_error ("%s", err);
113     free (out);
114     free (err);
115     return NULL;
116   }
117
118   free (err);
119
120   return convert_lvm_output (out, NULL);
121 }
122
123 char **
124 do_lvs (void)
125 {
126   char *out, *err;
127   int r;
128
129   r = command (&out, &err,
130                "/sbin/lvm", "lvs",
131                "-o", "vg_name,lv_name", "--noheadings",
132                "--separator", "/", NULL);
133   if (r == -1) {
134     reply_with_error ("%s", err);
135     free (out);
136     free (err);
137     return NULL;
138   }
139
140   free (err);
141
142   return convert_lvm_output (out, "/dev/");
143 }
144
145 /* These were so complex to implement that I ended up auto-generating
146  * the code.  That code is in stubs.c, and it is generated as usual
147  * by generator.ml.
148  */
149 guestfs_lvm_int_pv_list *
150 do_pvs_full (void)
151 {
152   return parse_command_line_pvs ();
153 }
154
155 guestfs_lvm_int_vg_list *
156 do_vgs_full (void)
157 {
158   return parse_command_line_vgs ();
159 }
160
161 guestfs_lvm_int_lv_list *
162 do_lvs_full (void)
163 {
164   return parse_command_line_lvs ();
165 }