1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2010-2011 Red Hat Inc.
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.
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.
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.
31 /* Does the current line match the regexp /^\s*filter\s*=/ */
33 is_filter_line (const char *line)
35 while (*line && c_isspace (*line))
40 if (! STRPREFIX (line, "filter"))
44 while (*line && c_isspace (*line))
55 /* Rewrite the 'filter = [ ... ]' line in /etc/lvm/lvm.conf. */
57 set_filter (const char *filter)
59 FILE *ifp = fopen ("/etc/lvm/lvm.conf", "r");
61 reply_with_perror ("open: /etc/lvm/lvm.conf");
64 FILE *ofp = fopen ("/etc/lvm/lvm.conf.new", "w");
66 reply_with_perror ("open: /etc/lvm/lvm.conf.new");
73 while (getline (&line, &len, ifp) != -1) {
75 if (is_filter_line (line)) {
76 r = fprintf (ofp, " filter = [ %s ]\n", filter);
78 r = fprintf (ofp, "%s", line);
81 /* NB. fprintf doesn't set errno on error. */
82 reply_with_error ("/etc/lvm/lvm.conf.new: write failed");
86 unlink ("/etc/lvm/lvm.conf.new");
93 if (fclose (ifp) == EOF) {
94 reply_with_perror ("/etc/lvm/lvm.conf.new");
95 unlink ("/etc/lvm/lvm.conf.new");
99 if (fclose (ofp) == EOF) {
100 reply_with_perror ("/etc/lvm/lvm.conf.new");
101 unlink ("/etc/lvm/lvm.conf.new");
105 if (rename ("/etc/lvm/lvm.conf.new", "/etc/lvm/lvm.conf") == -1) {
106 reply_with_perror ("rename: /etc/lvm/lvm.conf");
107 unlink ("/etc/lvm/lvm.conf.new");
115 vgchange (const char *vgchange_flag)
118 int r = command (NULL, &err, "lvm", "vgchange", vgchange_flag, NULL);
120 reply_with_error ("vgchange: %s", err);
129 /* Deactivate all VGs. */
133 return vgchange ("-an");
136 /* Reactivate all VGs. */
140 return vgchange ("-ay");
143 /* Clear the cache and rescan. */
147 unlink ("/etc/lvm/cache/.cache");
150 int r = command (NULL, &err, "lvm", "vgscan", NULL);
152 reply_with_error ("vgscan: %s", err);
161 /* Construct the new, specific filter string. We can assume that
162 * the 'devices' array does not contain any regexp metachars,
163 * because it's already been checked by the stub code.
166 make_filter_string (char *const *devices)
170 for (i = 0; devices[i] != NULL; ++i)
171 len += strlen (devices[i]) + 16;
173 char *filter = malloc (len);
174 if (filter == NULL) {
175 reply_with_perror ("malloc");
180 for (i = 0; devices[i] != NULL; ++i) {
181 /* Because of the way matching works in LVM, each match clause
183 * "a|^/dev/sda|", for whole block devices, or
184 * "a|^/dev/sda1$|", for single partitions
185 * (the assumption being we have <= 26 block devices XXX).
187 size_t slen = strlen (devices[i]);
190 if (c_isdigit (devices[i][slen-1]))
191 snprintf (str, slen+16, "\"a|^%s$|\", ", devices[i]);
193 snprintf (str, slen+16, "\"a|^%s|\", ", devices[i]);
198 strcpy (p, "\"r|.*|\"");
200 return filter; /* Caller must free. */
204 do_lvm_set_filter (char *const *devices)
206 char *filter = make_filter_string (devices);
210 if (deactivate () == -1) {
215 int r = set_filter (filter);
223 return reactivate ();
227 do_lvm_clear_filter (void)
229 if (deactivate () == -1)
232 if (set_filter ("\"a/.*/\"") == -1)
238 return reactivate ();