]> git.ipfire.org Git - thirdparty/util-linux.git/blob - mount/swapon.c
Imported from util-linux-2.12h tarball.
[thirdparty/util-linux.git] / mount / swapon.c
1 /*
2 * A swapon(8)/swapoff(8) for Linux 0.99.
3 * swapon.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
4 *
5 * 1997-02-xx <Vincent.Renardias@waw.com>
6 * - added '-s' (summary option)
7 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
8 * - added Native Language Support
9 * 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
10 * - fixed strerr(errno) in gettext calls
11 * 2001-03-22 Erik Troan <ewt@redhat.com>
12 * - added -e option for -a
13 * - -a shouldn't try to add swaps that are already enabled
14 */
15
16 #include <ctype.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <getopt.h>
20 #include <string.h>
21 #include <mntent.h>
22 #include <errno.h>
23 #include <sys/stat.h>
24 #include "swap_constants.h"
25 #include "swapargs.h"
26 #include "nls.h"
27
28 #define streq(s, t) (strcmp ((s), (t)) == 0)
29
30 #define _PATH_FSTAB "/etc/fstab"
31 #define PROC_SWAPS "/proc/swaps"
32
33 #define SWAPON_NEEDS_TWO_ARGS
34
35 #define QUIET 1
36
37 int all = 0;
38 int verbose = 0;
39 int priority = -1; /* non-prioritized swap by default */
40
41 /* If true, don't complain if the device/file doesn't exist */
42 int ifexists = 0;
43
44 extern char version[];
45 static char *program_name;
46
47 static struct option longswaponopts[] = {
48 /* swapon only */
49 { "priority", required_argument, 0, 'p' },
50 { "ifexists", 0, 0, 'e' },
51 { "summary", 0, 0, 's' },
52 /* also for swapoff */
53 { "all", 0, 0, 'a' },
54 { "help", 0, 0, 'h' },
55 { "verbose", 0, 0, 'v' },
56 { "version", 0, 0, 'V' },
57 { NULL, 0, 0, 0 }
58 };
59
60 static struct option *longswapoffopts = &longswaponopts[2];
61
62 static void
63 swapon_usage(FILE *fp, int n) {
64 fprintf(fp, _("usage: %s [-hV]\n"
65 " %s -a [-e] [-v]\n"
66 " %s [-v] [-p priority] special ...\n"
67 " %s [-s]\n"),
68 program_name, program_name, program_name, program_name);
69 exit(n);
70 }
71
72 static void
73 swapoff_usage(FILE *fp, int n) {
74 fprintf(fp, _("usage: %s [-hV]\n"
75 " %s -a [-v]\n"
76 " %s [-v] special ...\n"),
77 program_name, program_name, program_name);
78 exit(n);
79 }
80
81 #ifdef SWAPON_HAS_TWO_ARGS
82 #define SWAPON_NEEDS_TWO_ARGS
83 #endif
84
85 #ifdef SWAPON_NEEDS_TWO_ARGS
86 #ifdef SWAPON_HAS_TWO_ARGS
87 /* libc is OK */
88 #include <unistd.h>
89 #else
90 /* We want a swapon with two args, but have an old libc.
91 Build the kernel call by hand. */
92 #include <linux/unistd.h>
93 static
94 _syscall2(int, swapon, const char *, path, int, flags);
95 static
96 _syscall1(int, swapoff, const char *, path);
97 #endif
98 #else
99 /* just do as libc says */
100 #include <unistd.h>
101 #endif
102
103
104 /*
105 * contents of /proc/swaps
106 */
107 static int numSwaps;
108 static char **swapFiles; /* array of swap file and partition names */
109
110 static void
111 read_proc_swaps(void) {
112 FILE *swaps;
113 char line[1024];
114 char *p;
115
116 numSwaps = 0;
117 swapFiles = NULL;
118
119 swaps = fopen(PROC_SWAPS, "r");
120 if (swaps == NULL)
121 return; /* nothing wrong */
122
123 /* skip the first line */
124 fgets(line, sizeof(line), swaps);
125
126 while (fgets(line, sizeof(line), swaps)) {
127 /*
128 * Cut the line "swap_device ... more info" after device.
129 * This will fail with names with embedded spaces.
130 */
131 for (p = line; *p && *p != ' '; p++);
132 *p = 0;
133
134 numSwaps++;
135 swapFiles = realloc(swapFiles,
136 numSwaps * sizeof(*swapFiles));
137 swapFiles[numSwaps-1] = strdup(line);
138 }
139 fclose(swaps);
140 }
141
142 static int
143 is_in_proc_swaps(char *fname) {
144 int i;
145
146 for (i = 0; i < numSwaps; i++)
147 if (!strcmp(fname, swapFiles[i]))
148 return 1;
149 return 0;
150 }
151
152 static int
153 display_summary(void)
154 {
155 FILE *swaps;
156 char line[1024] ;
157
158 if ((swaps = fopen(PROC_SWAPS, "r")) == NULL) {
159 int errsv = errno;
160 fprintf(stderr, "%s: %s: %s\n", program_name, PROC_SWAPS,
161 strerror(errsv));
162 return -1 ;
163 }
164
165 while (fgets(line, sizeof(line), swaps))
166 printf("%s", line);
167
168 fclose(swaps);
169 return 0 ;
170 }
171
172 static int
173 do_swapon(const char *special, int prio) {
174 int status;
175 struct stat st;
176
177 if (verbose)
178 printf(_("%s on %s\n"), program_name, special);
179
180 if (stat(special, &st) < 0) {
181 int errsv = errno;
182 fprintf(stderr, _("swapon: cannot stat %s: %s\n"),
183 special, strerror(errsv));
184 return -1;
185 }
186
187 /* people generally dislike this warning - now it is printed
188 only when `verbose' is set */
189 if (verbose) {
190 int permMask = (S_ISBLK(st.st_mode) ? 07007 : 07077);
191
192 if ((st.st_mode & permMask) != 0) {
193 fprintf(stderr, _("swapon: warning: %s has "
194 "insecure permissions %04o, "
195 "%04o suggested\n"),
196 special, st.st_mode & 07777,
197 ~permMask & 0666);
198 }
199 }
200
201 /* test for holes by LBT */
202 if (S_ISREG(st.st_mode)) {
203 if (st.st_blocks * 512 < st.st_size) {
204 fprintf(stderr,
205 _("swapon: Skipping file %s - it appears "
206 "to have holes.\n"),
207 special);
208 return -1;
209 }
210 }
211
212 #ifdef SWAPON_NEEDS_TWO_ARGS
213 {
214 int flags = 0;
215
216 #ifdef SWAP_FLAG_PREFER
217 if (prio >= 0) {
218 if (prio > SWAP_FLAG_PRIO_MASK)
219 prio = SWAP_FLAG_PRIO_MASK;
220 flags = SWAP_FLAG_PREFER
221 | ((prio & SWAP_FLAG_PRIO_MASK)
222 << SWAP_FLAG_PRIO_SHIFT);
223 }
224 #endif
225 status = swapon(special, flags);
226 }
227 #else
228 status = swapon(special);
229 #endif
230 if (status < 0) {
231 int errsv = errno;
232 fprintf(stderr, "%s: %s: %s\n", program_name,
233 special, strerror(errsv));
234 }
235
236 return status;
237 }
238
239 static int
240 do_swapoff(const char *special, int quiet) {
241 if (verbose)
242 printf(_("%s on %s\n"), program_name, special);
243
244 if (swapoff(special) == 0)
245 return 0; /* success */
246
247 if (errno == EPERM) {
248 fprintf(stderr, _("Not superuser.\n"));
249 exit(1); /* any further swapoffs will also fail */
250 }
251
252 if (!quiet || errno == ENOMEM) {
253 int errsv = errno;
254 fprintf(stderr, "%s: %s: %s\n", program_name,
255 special, strerror(errsv));
256 }
257 return -1;
258 }
259
260 static int
261 main_swapon(int argc, char *argv[]) {
262 FILE *fp;
263 struct mntent *fstab;
264 int status = 0;
265 int c;
266
267 while ((c = getopt_long(argc, argv, "ahep:svV",
268 longswaponopts, NULL)) != -1) {
269 switch (c) {
270 case 'a': /* all */
271 ++all;
272 break;
273 case 'h': /* help */
274 swapon_usage(stdout, 0);
275 break;
276 case 'p': /* priority */
277 priority = atoi(optarg);
278 break;
279 case 'e': /* ifexists */
280 ifexists = 1;
281 break;
282 case 's': /* status report */
283 status = display_summary();
284 exit(status);
285 case 'v': /* be chatty */
286 ++verbose;
287 break;
288 case 'V': /* version */
289 printf("%s: %s\n", program_name, version);
290 exit(0);
291 case 0:
292 break;
293 case '?':
294 default:
295 swapon_usage(stderr, 1);
296 }
297 }
298 argv += optind;
299
300 if (!all && *argv == NULL)
301 swapon_usage(stderr, 2);
302
303 if (ifexists && (!all || strcmp(program_name, "swapon")))
304 swapon_usage(stderr, 1);
305
306 if (all) {
307 read_proc_swaps();
308
309 fp = setmntent(_PATH_FSTAB, "r");
310 if (fp == NULL) {
311 int errsv = errno;
312 fprintf(stderr, _("%s: cannot open %s: %s\n"),
313 program_name, _PATH_FSTAB, strerror(errsv));
314 exit(2);
315 }
316 while ((fstab = getmntent(fp)) != NULL) {
317 char *special = fstab->mnt_fsname;
318
319 if (streq(fstab->mnt_type, MNTTYPE_SWAP) &&
320 !is_in_proc_swaps(special)
321 && (!ifexists || !access(special, R_OK))) {
322 /* parse mount options; */
323 char *opt, *opts = strdup(fstab->mnt_opts);
324
325 for (opt = strtok(opts, ","); opt != NULL;
326 opt = strtok(NULL, ","))
327 if (strncmp(opt, "pri=", 4) == 0)
328 priority = atoi(opt+4);
329 status |= do_swapon(special, priority);
330 }
331 }
332 fclose(fp);
333 }
334
335 while (*argv != NULL)
336 status |= do_swapon(*argv++, priority);
337
338 return status;
339 }
340
341 static int
342 main_swapoff(int argc, char *argv[]) {
343 FILE *fp;
344 struct mntent *fstab;
345 int status = 0;
346 int c, i;
347
348 while ((c = getopt_long(argc, argv, "ahvV",
349 longswapoffopts, NULL)) != -1) {
350 switch (c) {
351 case 'a': /* all */
352 ++all;
353 break;
354 case 'h': /* help */
355 swapoff_usage(stdout, 0);
356 break;
357 case 'v': /* be chatty */
358 ++verbose;
359 break;
360 case 'V': /* version */
361 printf("%s: %s\n", program_name, version);
362 exit(0);
363 case 0:
364 break;
365 case '?':
366 default:
367 swapoff_usage(stderr, 1);
368 }
369 }
370 argv += optind;
371
372 if (!all && *argv == NULL)
373 swapoff_usage(stderr, 2);
374
375 /*
376 * swapoff any explicitly given arguments.
377 * Complain in case the swapoff call fails.
378 */
379 while (*argv != NULL)
380 status |= do_swapoff(*argv++, !QUIET);
381
382 if (all) {
383 /*
384 * In case /proc/swaps exists, unmount stuff listed there.
385 * We are quiet but report errors in status.
386 * Errors might mean that /proc/swaps
387 * exists as ordinary file, not in procfs.
388 * do_swapoff() exits immediately on EPERM.
389 */
390 read_proc_swaps();
391 for(i=0; i<numSwaps; i++)
392 status |= do_swapoff(swapFiles[i], QUIET);
393
394 /*
395 * Unmount stuff mentioned in /etc/fstab.
396 * Probably it was unmounted already, so errors are not bad.
397 * Doing swapoff -a twice should not give error messages.
398 */
399 fp = setmntent(_PATH_FSTAB, "r");
400 if (fp == NULL) {
401 int errsv = errno;
402 fprintf(stderr, _("%s: cannot open %s: %s\n"),
403 program_name, _PATH_FSTAB, strerror(errsv));
404 exit(2);
405 }
406 while ((fstab = getmntent(fp)) != NULL) {
407 if (streq(fstab->mnt_type, MNTTYPE_SWAP) &&
408 !is_in_proc_swaps(fstab->mnt_fsname))
409 do_swapoff(fstab->mnt_fsname, QUIET);
410 }
411 fclose(fp);
412 }
413
414 return status;
415 }
416
417 int
418 main(int argc, char *argv[]) {
419 char *p;
420
421 setlocale(LC_ALL, "");
422 bindtextdomain(PACKAGE, LOCALEDIR);
423 textdomain(PACKAGE);
424
425 program_name = argv[0];
426 p = strrchr(program_name, '/');
427 if (p)
428 program_name = p+1;
429
430 if (streq(program_name, "swapon"))
431 return main_swapon(argc, argv);
432 else
433 return main_swapoff(argc, argv);
434 }