gnulib: Rebase to latest.
[libguestfs.git] / daemon / swap.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
26 #include "guestfs_protocol.h"
27 #include "daemon.h"
28 #include "actions.h"
29 #include "optgroups.h"
30
31 #include "ignore-value.h"
32
33 /* Confirmed this is true for Linux swap partitions from the Linux sources. */
34 #define SWAP_LABEL_MAX 16
35
36 /* Convenient place to test for the later version of e2fsprogs
37  * and util-linux which supports -U parameters to specify UUIDs.
38  * (Not supported in RHEL 5).
39  */
40 int
41 optgroup_linuxfsuuid_available (void)
42 {
43   char *err;
44   int av;
45
46   /* Upstream util-linux have been gradually changing '--help' to go
47    * from stderr to stdout, and changing the return code from 1 to 0.
48    * Thus we need to fold stdout and stderr together, and ignore the
49    * return code.
50    */
51   ignore_value (commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
52                           "mkswap", "--help", NULL));
53
54   av = strstr (err, "-U") != NULL;
55   free (err);
56   return av;
57 }
58
59 static int
60 mkswap (const char *device, const char *flag, const char *value)
61 {
62   char *err;
63   int r;
64
65   if (!flag)
66     r = command (NULL, &err, "mkswap", "-f", device, NULL);
67   else
68     r = command (NULL, &err, "mkswap", "-f", flag, value, device, NULL);
69
70   if (r == -1) {
71     reply_with_error ("%s", err);
72     free (err);
73     return -1;
74   }
75
76   free (err);
77
78   return 0;
79 }
80
81 int
82 do_mkswap (const char *device)
83 {
84   return mkswap (device, NULL, NULL);
85 }
86
87 int
88 do_mkswap_L (const char *label, const char *device)
89 {
90   if (strlen (label) > SWAP_LABEL_MAX) {
91     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
92                       label, SWAP_LABEL_MAX);
93     return -1;
94   }
95
96   return mkswap (device, "-L", label);
97 }
98
99 int
100 do_mkswap_U (const char *uuid, const char *device)
101 {
102   return mkswap (device, "-U", uuid);
103 }
104
105 int
106 do_mkswap_file (const char *path)
107 {
108   char *buf;
109   int r;
110
111   buf = sysroot_path (path);
112   if (!buf) {
113     reply_with_perror ("malloc");
114     return -1;
115   }
116
117   r = mkswap (buf, NULL, NULL);
118   free (buf);
119   return r;
120 }
121
122 static int
123 swaponoff (const char *cmd, const char *flag, const char *value)
124 {
125   char *err;
126   int r;
127
128   if (!flag)
129     r = command (NULL, &err, cmd, value, NULL);
130   else
131     r = command (NULL, &err, cmd, flag, value, NULL);
132
133   if (r == -1) {
134     reply_with_error ("%s: %s", value, err);
135     free (err);
136     return -1;
137   }
138
139   free (err);
140
141   /* Possible fix for RHBZ#516096.  It probably doesn't hurt to do
142    * this in any case.
143    */
144   udev_settle ();
145
146   return 0;
147 }
148
149 int
150 do_swapon_device (const char *device)
151 {
152   return swaponoff ("swapon", NULL, device);
153 }
154
155 int
156 do_swapoff_device (const char *device)
157 {
158   return swaponoff ("swapoff", NULL, device);
159 }
160
161 int
162 do_swapon_file (const char *path)
163 {
164   char *buf;
165   int r;
166
167   buf = sysroot_path (path);
168   if (!buf) {
169     reply_with_perror ("malloc");
170     return -1;
171   }
172
173   r = swaponoff ("swapon", NULL, buf);
174   free (buf);
175   return r;
176 }
177
178 int
179 do_swapoff_file (const char *path)
180 {
181   char *buf;
182   int r;
183
184   buf = sysroot_path (path);
185   if (!buf) {
186     reply_with_perror ("malloc");
187     return -1;
188   }
189
190   r = swaponoff ("swapoff", NULL, buf);
191   free (buf);
192   return r;
193 }
194
195 int
196 do_swapon_label (const char *label)
197 {
198   if (strlen (label) > SWAP_LABEL_MAX) {
199     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
200                       label, SWAP_LABEL_MAX);
201     return -1;
202   }
203
204   return swaponoff ("swapon", "-L", label);
205 }
206
207 int
208 do_swapoff_label (const char *label)
209 {
210   if (strlen (label) > SWAP_LABEL_MAX) {
211     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
212                       label, SWAP_LABEL_MAX);
213     return -1;
214   }
215
216   return swaponoff ("swapoff", "-L", label);
217 }
218
219 int
220 do_swapon_uuid (const char *uuid)
221 {
222   return swaponoff ("swapon", "-U", uuid);
223 }
224
225 int
226 do_swapoff_uuid (const char *uuid)
227 {
228   return swaponoff ("swapoff", "-U", uuid);
229 }