1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2010 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)
60 fprintf (stderr, "LVM: setting device filter to %s\n", filter);
62 FILE *ifp = fopen ("/etc/lvm/lvm.conf", "r");
64 reply_with_perror ("open: /etc/lvm/lvm.conf");
67 FILE *ofp = fopen ("/etc/lvm/lvm.conf.new", "w");
69 reply_with_perror ("open: /etc/lvm/lvm.conf.new");
76 while (getline (&line, &len, ifp) != -1) {
78 if (is_filter_line (line)) {
80 fprintf (stderr, "LVM: replacing config line:\n%s", line);
81 r = fprintf (ofp, " filter = [ %s ]\n", filter);
83 r = fprintf (ofp, "%s", line);
86 /* NB. fprintf doesn't set errno on error. */
87 reply_with_error ("/etc/lvm/lvm.conf.new: write failed");
91 unlink ("/etc/lvm/lvm.conf.new");
98 if (fclose (ifp) == EOF) {
99 reply_with_perror ("/etc/lvm/lvm.conf.new");
100 unlink ("/etc/lvm/lvm.conf.new");
104 if (fclose (ofp) == EOF) {
105 reply_with_perror ("/etc/lvm/lvm.conf.new");
106 unlink ("/etc/lvm/lvm.conf.new");
110 if (rename ("/etc/lvm/lvm.conf.new", "/etc/lvm/lvm.conf") == -1) {
111 reply_with_perror ("rename: /etc/lvm/lvm.conf");
112 unlink ("/etc/lvm/lvm.conf.new");
120 vgchange (const char *vgchange_flag)
123 int r = command (NULL, &err, "lvm", "vgchange", vgchange_flag, NULL);
125 reply_with_error ("vgchange: %s", err);
134 /* Deactivate all VGs. */
138 return vgchange ("-an");
141 /* Reactivate all VGs. */
145 return vgchange ("-ay");
148 /* Clear the cache and rescan. */
152 unlink ("/etc/lvm/cache/.cache");
155 int r = command (NULL, &err, "lvm", "vgscan", NULL);
157 reply_with_error ("vgscan: %s", err);
166 /* Construct the new, specific filter string. We can assume that
167 * the 'devices' array does not contain any regexp metachars,
168 * because it's already been checked by the stub code.
171 make_filter_string (char *const *devices)
175 for (i = 0; devices[i] != NULL; ++i)
176 len += strlen (devices[i]) + 16;
178 char *filter = malloc (len);
179 if (filter == NULL) {
180 reply_with_perror ("malloc");
185 for (i = 0; devices[i] != NULL; ++i) {
186 /* Because of the way matching works in LVM, each match clause
188 * "a|^/dev/sda|", for whole block devices, or
189 * "a|^/dev/sda1$|", for single partitions
190 * (the assumption being we have <= 26 block devices XXX).
192 size_t slen = strlen (devices[i]);
195 if (c_isdigit (devices[i][slen-1]))
196 snprintf (str, slen+16, "\"a|^%s$|\", ", devices[i]);
198 snprintf (str, slen+16, "\"a|^%s|\", ", devices[i]);
203 strcpy (p, "\"r|.*|\"");
205 return filter; /* Caller must free. */
209 do_lvm_set_filter (char *const *devices)
211 char *filter = make_filter_string (devices);
215 if (deactivate () == -1) {
220 int r = set_filter (filter);
228 return reactivate ();
232 do_lvm_clear_filter (void)
234 if (deactivate () == -1)
237 if (set_filter ("\"a/.*/\"") == -1)
243 return reactivate ();