99fb5639d83aa3e9bb41c074bf64118f3c3b9213
[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., 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
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   /* Ignore return code - mkswap --help *will* fail. */
47   ignore_value (command (NULL, &err, "mkswap", "--help", NULL));
48
49   av = strstr (err, "-U") != NULL;
50   free (err);
51   return av;
52 }
53
54 static int
55 mkswap (const char *device, const char *flag, const char *value)
56 {
57   char *err;
58   int r;
59
60   if (!flag)
61     r = command (NULL, &err, "mkswap", "-f", device, NULL);
62   else
63     r = command (NULL, &err, "mkswap", "-f", flag, value, device, NULL);
64
65   if (r == -1) {
66     reply_with_error ("%s", err);
67     free (err);
68     return -1;
69   }
70
71   free (err);
72
73   return 0;
74 }
75
76 int
77 do_mkswap (const char *device)
78 {
79   return mkswap (device, NULL, NULL);
80 }
81
82 int
83 do_mkswap_L (const char *label, const char *device)
84 {
85   if (strlen (label) > SWAP_LABEL_MAX) {
86     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
87                       label, SWAP_LABEL_MAX);
88     return -1;
89   }
90
91   return mkswap (device, "-L", label);
92 }
93
94 int
95 do_mkswap_U (const char *uuid, const char *device)
96 {
97   return mkswap (device, "-U", uuid);
98 }
99
100 int
101 do_mkswap_file (const char *path)
102 {
103   char *buf;
104   int r;
105
106   buf = sysroot_path (path);
107   if (!buf) {
108     reply_with_perror ("malloc");
109     return -1;
110   }
111
112   r = mkswap (buf, NULL, NULL);
113   free (buf);
114   return r;
115 }
116
117 static int
118 swaponoff (const char *cmd, const char *flag, const char *value)
119 {
120   char *err;
121   int r;
122
123   if (!flag)
124     r = command (NULL, &err, cmd, value, NULL);
125   else
126     r = command (NULL, &err, cmd, flag, value, NULL);
127
128   if (r == -1) {
129     reply_with_error ("%s: %s", value, err);
130     free (err);
131     return -1;
132   }
133
134   free (err);
135
136   /* Possible fix for RHBZ#516096.  It probably doesn't hurt to do
137    * this in any case.
138    */
139   udev_settle ();
140
141   return 0;
142 }
143
144 int
145 do_swapon_device (const char *device)
146 {
147   return swaponoff ("swapon", NULL, device);
148 }
149
150 int
151 do_swapoff_device (const char *device)
152 {
153   return swaponoff ("swapoff", NULL, device);
154 }
155
156 int
157 do_swapon_file (const char *path)
158 {
159   char *buf;
160   int r;
161
162   buf = sysroot_path (path);
163   if (!buf) {
164     reply_with_perror ("malloc");
165     return -1;
166   }
167
168   r = swaponoff ("swapon", NULL, buf);
169   free (buf);
170   return r;
171 }
172
173 int
174 do_swapoff_file (const char *path)
175 {
176   char *buf;
177   int r;
178
179   buf = sysroot_path (path);
180   if (!buf) {
181     reply_with_perror ("malloc");
182     return -1;
183   }
184
185   r = swaponoff ("swapoff", NULL, buf);
186   free (buf);
187   return r;
188 }
189
190 int
191 do_swapon_label (const char *label)
192 {
193   if (strlen (label) > SWAP_LABEL_MAX) {
194     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
195                       label, SWAP_LABEL_MAX);
196     return -1;
197   }
198
199   return swaponoff ("swapon", "-L", label);
200 }
201
202 int
203 do_swapoff_label (const char *label)
204 {
205   if (strlen (label) > SWAP_LABEL_MAX) {
206     reply_with_error ("%s: Linux swap labels are limited to %d bytes",
207                       label, SWAP_LABEL_MAX);
208     return -1;
209   }
210
211   return swaponoff ("swapoff", "-L", label);
212 }
213
214 int
215 do_swapon_uuid (const char *uuid)
216 {
217   return swaponoff ("swapon", "-U", uuid);
218 }
219
220 int
221 do_swapoff_uuid (const char *uuid)
222 {
223   return swaponoff ("swapoff", "-U", uuid);
224 }