]> git.ipfire.org Git - thirdparty/util-linux.git/blame - mount/swapon.c
swapon: move DELETED_SUFFIX to include/pathnames.h
[thirdparty/util-linux.git] / mount / swapon.c
CommitLineData
6dbe3af9
KZ
1/*
2 * A swapon(8)/swapoff(8) for Linux 0.99.
6dbe3af9 3 */
fd6b7a7f
KZ
4#include <stdlib.h>
5#include <stdio.h>
6#include <getopt.h>
7#include <string.h>
8#include <mntent.h>
9#include <errno.h>
5c36a0eb 10#include <sys/stat.h>
ffa63a3d 11#include <unistd.h>
6274b987
KC
12#include <sys/types.h>
13#include <sys/wait.h>
14#include <fcntl.h>
3399a218 15#include <stdint.h>
d51d05d3 16#include <err.h>
81772d3c 17
3399a218
MK
18#include "bitops.h"
19#include "blkdev.h"
5c36a0eb 20#include "swap_constants.h"
7eda085c 21#include "nls.h"
0964afe1 22#include "fsprobe.h"
4e270e3f 23#include "pathnames.h"
3399a218 24#include "swapheader.h"
bf71ef07 25#include "mangle.h"
167eaed7 26
6274b987
KC
27#define PATH_MKSWAP "/sbin/mkswap"
28
ffa63a3d
MF
29#ifdef HAVE_SYS_SWAP_H
30# include <sys/swap.h>
31#endif
32
33#ifndef SWAPON_HAS_TWO_ARGS
34/* libc is insane, let's call the kernel */
35# include <sys/syscall.h>
36# define swapon(path, flags) syscall(SYS_swapon, path, flags)
37# define swapoff(path) syscall(SYS_swapoff, path)
38#endif
39
fd6b7a7f
KZ
40#define streq(s, t) (strcmp ((s), (t)) == 0)
41
63cccae4 42#define QUIET 1
12ac2bbe 43#define CANONIC 1
63cccae4 44
3399a218
MK
45#define MAX_PAGESIZE (64 * 1024)
46
e8be80dd
KZ
47enum {
48 SIG_SWAPSPACE = 1,
49 SIG_SWSUSPEND
50};
51
617d8a3b
KZ
52#define SWAP_SIGNATURE "SWAPSPACE2"
53#define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
54
81772d3c 55int all;
726f69e2 56int priority = -1; /* non-prioritized swap by default */
6dbe3af9 57
95f1bdee 58/* If true, don't complain if the device/file doesn't exist */
81772d3c 59int ifexists;
0d761944 60int fixpgsz;
81772d3c
KZ
61
62int verbose;
63char *progname;
95f1bdee 64
63cccae4
KZ
65static struct option longswaponopts[] = {
66 /* swapon only */
67 { "priority", required_argument, 0, 'p' },
95f1bdee 68 { "ifexists", 0, 0, 'e' },
63cccae4 69 { "summary", 0, 0, 's' },
0d761944 70 { "fixpgsz", 0, 0, 'f' },
63cccae4
KZ
71 /* also for swapoff */
72 { "all", 0, 0, 'a' },
73 { "help", 0, 0, 'h' },
74 { "verbose", 0, 0, 'v' },
75 { "version", 0, 0, 'V' },
76 { NULL, 0, 0, 0 }
6dbe3af9
KZ
77};
78
0d761944 79static struct option *longswapoffopts = &longswaponopts[4];
63cccae4 80
12ac2bbe
KZ
81static int cannot_find(const char *special);
82
240e20b5
KZ
83#define PRINT_USAGE_SPECIAL(_fp) \
84 fprintf(_fp, _( \
d08a2b44 85 "The <special> parameter:\n" \
ce6479e2
BS
86 " {-L label | LABEL=label} LABEL of device to be used\n" \
87 " {-U uuid | UUID=uuid} UUID of device to be used\n" \
88 " <device> name of device to be used\n" \
89 " <file> name of file to be used\n\n"))
240e20b5 90
6dbe3af9 91static void
63cccae4 92swapon_usage(FILE *fp, int n) {
240e20b5 93 fprintf(fp, _("\nUsage:\n"
0d761944
KZ
94 " %1$s -a [-e] [-v] [-f] enable all swaps from /etc/fstab\n"
95 " %1$s [-p priority] [-v] [-f] <special> enable given swap\n"
d08a2b44
KZ
96 " %1$s -s display swap usage summary\n"
97 " %1$s -h display help\n"
98 " %1$s -V display version\n\n"), progname);
240e20b5
KZ
99
100 PRINT_USAGE_SPECIAL(fp);
101
63cccae4
KZ
102 exit(n);
103}
104
105static void
106swapoff_usage(FILE *fp, int n) {
240e20b5 107 fprintf(fp, _("\nUsage:\n"
ce6479e2
BS
108 " %1$s -a [-v] disable all swaps\n"
109 " %1$s [-v] <special> disable given swap\n"
110 " %1$s -h display help\n"
111 " %1$s -V display version\n\n"), progname);
240e20b5
KZ
112
113 PRINT_USAGE_SPECIAL(fp);
114
63cccae4 115 exit(n);
6dbe3af9
KZ
116}
117
63cccae4
KZ
118/*
119 * contents of /proc/swaps
120 */
121static int numSwaps;
122static char **swapFiles; /* array of swap file and partition names */
6dbe3af9 123
63cccae4
KZ
124static void
125read_proc_swaps(void) {
126 FILE *swaps;
127 char line[1024];
a47f2e66 128 char *p, **q;
dac4cc1d 129 size_t sz;
5c36a0eb 130
63cccae4
KZ
131 numSwaps = 0;
132 swapFiles = NULL;
fd6b7a7f 133
4e270e3f 134 swaps = fopen(_PATH_PROC_SWAPS, "r");
63cccae4
KZ
135 if (swaps == NULL)
136 return; /* nothing wrong */
137
138 /* skip the first line */
03f0d3e9 139 if (!fgets(line, sizeof(line), swaps)) {
d08cd85f
MF
140 /* do not whine about an empty file */
141 if (ferror(swaps))
142 warn(_("%s: unexpected file format"), _PATH_PROC_SWAPS);
03f0d3e9
RD
143 fclose(swaps);
144 return;
145 }
d08cd85f
MF
146 /* make sure the first line is the header */
147 if (line[0] != '\0' && strncmp(line, "Filename\t", 9))
148 goto valid_first_line;
149
63cccae4 150 while (fgets(line, sizeof(line), swaps)) {
d08cd85f 151 valid_first_line:
63cccae4
KZ
152 /*
153 * Cut the line "swap_device ... more info" after device.
154 * This will fail with names with embedded spaces.
155 */
156 for (p = line; *p && *p != ' '; p++);
dac4cc1d
KZ
157 *p = '\0';
158
159 /* the kernel can use " (deleted)" suffix for paths
160 * in /proc/swaps, we have to remove this junk.
161 */
162 sz = strlen(line);
865deca2
KZ
163 if (sz > PATH_DELETED_SUFFIX_SZ) {
164 p = line + (sz - PATH_DELETED_SUFFIX_SZ);
165 if (strcmp(p, PATH_DELETED_SUFFIX) == 0)
dac4cc1d
KZ
166 *p = '\0';
167 }
6dbe3af9 168
a47f2e66
KZ
169 q = realloc(swapFiles, (numSwaps+1) * sizeof(*swapFiles));
170 if (q == NULL)
171 break;
172 swapFiles = q;
173
bf71ef07 174 swapFiles[numSwaps++] = unmangle(line);
63cccae4
KZ
175 }
176 fclose(swaps);
177}
178
179static int
756bfd01 180is_in_proc_swaps(const char *fname) {
63cccae4
KZ
181 int i;
182
183 for (i = 0; i < numSwaps; i++)
07d9b366 184 if (swapFiles[i] && !strcmp(fname, swapFiles[i]))
63cccae4
KZ
185 return 1;
186 return 0;
6dbe3af9
KZ
187}
188
fd6b7a7f
KZ
189static int
190display_summary(void)
191{
192 FILE *swaps;
63cccae4 193 char line[1024] ;
fd6b7a7f 194
4e270e3f 195 if ((swaps = fopen(_PATH_PROC_SWAPS, "r")) == NULL) {
d51d05d3 196 warn(_("%s: open failed"), _PATH_PROC_SWAPS);
41d8815a 197 return -1;
fd6b7a7f 198 }
e8f26419 199
63cccae4
KZ
200 while (fgets(line, sizeof(line), swaps))
201 printf("%s", line);
fd6b7a7f 202
e8f26419 203 fclose(swaps);
fd6b7a7f
KZ
204 return 0 ;
205}
206
6274b987
KC
207/* calls mkswap */
208static int
209swap_reinitialize(const char *device) {
210 const char *label = fsprobe_get_label_by_devname(device);
211 const char *uuid = fsprobe_get_uuid_by_devname(device);
212 pid_t pid;
213 int status, ret;
214 char *cmd[7];
215 int idx=0;
216
0d761944
KZ
217 warnx(_("%s: reinitializing the swap."), device);
218
6274b987
KC
219 switch((pid=fork())) {
220 case -1: /* fork error */
d51d05d3 221 warn(_("fork failed"));
6274b987
KC
222 return -1;
223
224 case 0: /* child */
225 cmd[idx++] = PATH_MKSWAP;
226 if (label && *label) {
227 cmd[idx++] = "-L";
228 cmd[idx++] = (char *) label;
229 }
230 if (uuid && *uuid) {
231 cmd[idx++] = "-U";
232 cmd[idx++] = (char *) uuid;
233 }
234 cmd[idx++] = (char *) device;
235 cmd[idx++] = NULL;
236 execv(cmd[0], cmd);
d51d05d3 237 err(EXIT_FAILURE, _("execv failed"));
6274b987
KC
238
239 default: /* parent */
240 do {
241 if ((ret = waitpid(pid, &status, 0)) < 0
242 && errno == EINTR)
243 continue;
244 else if (ret < 0) {
d51d05d3 245 warn(_("waitpid failed"));
6274b987
KC
246 return -1;
247 }
248 } while (0);
249
250 /* mkswap returns: 0=suss, 1=error */
251 if (WIFEXITED(status) && WEXITSTATUS(status)==0)
252 return 0; /* ok */
253 }
254 return -1; /* error */
255}
256
617d8a3b
KZ
257static int
258swap_rewrite_signature(const char *devname, unsigned int pagesize)
259{
260 int fd, rc = -1;
261
262 fd = open(devname, O_WRONLY);
263 if (fd == -1) {
264 warn(_("%s: open failed"), devname);
265 return -1;
266 }
267
5dd53f43
KZ
268 if (lseek(fd, pagesize - SWAP_SIGNATURE_SZ, SEEK_SET) < 0) {
269 warn(_("%s: lseek failed"), devname);
617d8a3b 270 goto err;
5dd53f43 271 }
617d8a3b
KZ
272
273 if (write(fd, (void *) SWAP_SIGNATURE,
5dd53f43
KZ
274 SWAP_SIGNATURE_SZ) != SWAP_SIGNATURE_SZ) {
275 warn(_("%s: write signature failed"), devname);
617d8a3b 276 goto err;
5dd53f43 277 }
617d8a3b
KZ
278
279 rc = 0;
280err:
281 close(fd);
282 return rc;
283}
284
e8be80dd
KZ
285static int
286swap_detect_signature(const char *buf, int *sig)
3399a218 287{
e8be80dd
KZ
288 if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
289 memcmp(buf, "SWAPSPACE2", 10) == 0)
290 *sig = SIG_SWAPSPACE;
291
292 else if (memcmp(buf, "S1SUSPEND", 9) == 0 ||
293 memcmp(buf, "S2SUSPEND", 9) == 0 ||
294 memcmp(buf, "ULSUSPEND", 9) == 0 ||
295 memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0)
296 *sig = SIG_SWSUSPEND;
297 else
298 return 0;
3399a218 299
e8be80dd 300 return 1;
3399a218
MK
301}
302
e8be80dd
KZ
303static char *
304swap_get_header(int fd, int *sig, unsigned int *pagesize)
3399a218 305{
3399a218 306 char *buf;
e8be80dd
KZ
307 ssize_t datasz;
308 unsigned int page;
3399a218 309
e8be80dd
KZ
310 *pagesize = 0;
311 *sig = 0;
3399a218
MK
312
313 buf = malloc(MAX_PAGESIZE);
e8be80dd
KZ
314 if (!buf)
315 return NULL;
3399a218
MK
316
317 datasz = read(fd, buf, MAX_PAGESIZE);
e8be80dd
KZ
318 if (datasz == (ssize_t) -1)
319 goto err;
3399a218
MK
320
321 for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) {
322 /* skip 32k pagesize since this does not seem to
323 * be supported */
324 if (page == 0x8000)
325 continue;
326 /* the smallest swap area is PAGE_SIZE*10, it means
327 * 40k, that's less than MAX_PAGESIZE */
617d8a3b 328 if (datasz < (page - SWAP_SIGNATURE_SZ))
3399a218 329 break;
617d8a3b 330 if (swap_detect_signature(buf + page - SWAP_SIGNATURE_SZ, sig)) {
e8be80dd 331 *pagesize = page;
3399a218
MK
332 break;
333 }
334 }
335
e8be80dd
KZ
336 if (*pagesize)
337 return buf;
3399a218 338err:
e8be80dd
KZ
339 free(buf);
340 return NULL;
341}
342
343/* returns real size of swap space */
344unsigned long long
345swap_get_size(const char *hdr, const char *devname, unsigned int pagesize)
346{
347 unsigned int last_page = 0;
348 int swap_version = 0;
349 int flip = 0;
350 struct swap_header_v1_2 *s;
351
352 s = (struct swap_header_v1_2 *) hdr;
353 if (s->version == 1) {
354 swap_version = 1;
355 last_page = s->last_page;
356 } else if (swab32(s->version) == 1) {
357 flip = 1;
358 swap_version = 1;
359 last_page = swab32(s->last_page);
360 }
361 if (verbose)
04c94441
KZ
362 warnx(_("%s: found swap signature: version %d, "
363 "page-size %d, %s byte order"),
e8be80dd 364 devname,
e8be80dd 365 swap_version,
04c94441
KZ
366 pagesize / 1024,
367 flip ? _("different") : _("same"));
e8be80dd 368
98e9ff61 369 return ((unsigned long long) last_page + 1) * pagesize;
3399a218
MK
370}
371
63cccae4 372static int
05c79b78
KZ
373swapon_checks(const char *special)
374{
63cccae4 375 struct stat st;
05c79b78
KZ
376 int fd = -1, sig;
377 char *hdr = NULL;
e8be80dd
KZ
378 unsigned int pagesize;
379 unsigned long long devsize = 0;
63cccae4 380
63cccae4 381 if (stat(special, &st) < 0) {
d51d05d3 382 warn(_("%s: stat failed"), special);
05c79b78 383 goto err;
63cccae4
KZ
384 }
385
88530f9f
KZ
386 /* people generally dislike this warning - now it is printed
387 only when `verbose' is set */
388 if (verbose) {
389 int permMask = (S_ISBLK(st.st_mode) ? 07007 : 07077);
390
d51d05d3
KZ
391 if ((st.st_mode & permMask) != 0)
392 warnx(_("%s: insecure permissions %04o, %04o suggested."),
393 special, st.st_mode & 07777,
88530f9f 394 ~permMask & 0666);
88530f9f
KZ
395 }
396
397 /* test for holes by LBT */
398 if (S_ISREG(st.st_mode)) {
399 if (st.st_blocks * 512 < st.st_size) {
d51d05d3
KZ
400 warnx(_("%s: skipping - it appears to have holes."),
401 special);
05c79b78 402 goto err;
88530f9f 403 }
e8be80dd
KZ
404 devsize = st.st_size;
405 }
406
407 fd = open(special, O_RDONLY);
408 if (fd == -1) {
d51d05d3 409 warn(_("%s: open failed"), special);
05c79b78 410 goto err;
e8be80dd
KZ
411 }
412
05c79b78
KZ
413 if (S_ISBLK(st.st_mode) && blkdev_get_size(fd, &devsize)) {
414 warn(_("%s: get size failed"), special);
415 goto err;
e8be80dd
KZ
416 }
417
418 hdr = swap_get_header(fd, &sig, &pagesize);
419 if (!hdr) {
d51d05d3 420 warn(_("%s: read swap header failed"), special);
05c79b78 421 goto err;
88530f9f
KZ
422 }
423
e8be80dd
KZ
424 if (sig == SIG_SWAPSPACE && pagesize) {
425 unsigned long long swapsize =
426 swap_get_size(hdr, special, pagesize);
3399a218 427 if (verbose)
d51d05d3 428 warnx("%s: pagesize=%d, swapsize=%llu, devsize=%llu",
e8be80dd
KZ
429 special, pagesize, swapsize, devsize);
430
431 if (swapsize > devsize) {
432 if (verbose)
d51d05d3
KZ
433 warnx(_("%s: last_page 0x%08llx is larger"
434 " than actual size of swapspace"),
e8be80dd
KZ
435 special, swapsize);
436 } else if (getpagesize() != pagesize) {
0d761944 437 if (fixpgsz) {
93bfcc94 438 warnx(_("%s: swap format pagesize does not match."),
0d761944
KZ
439 special);
440 if (swap_reinitialize(special) < 0)
441 goto err;
442 } else
93bfcc94
KZ
443 warnx(_("%s: swap format pagesize does not match. "
444 "(Use --fixpgsz to reinitialize it.)"),
0d761944 445 special);
e8be80dd
KZ
446 }
447 } else if (sig == SIG_SWSUSPEND) {
448 /* We have to reinitialize swap with old (=useless) software suspend
449 * data. The problem is that if we don't do it, then we get data
450 * corruption the next time an attempt at unsuspending is made.
451 */
d51d05d3 452 warnx(_("%s: software suspend data detected. "
617d8a3b 453 "Rewriting the swap signature."),
d51d05d3 454 special);
617d8a3b 455 if (swap_rewrite_signature(special, pagesize) < 0)
05c79b78 456 goto err;
6274b987
KC
457 }
458
05c79b78
KZ
459 free(hdr);
460 close(fd);
461 return 0;
05c79b78
KZ
462err:
463 if (fd != -1)
464 close(fd);
465 free(hdr);
466 return -1;
467}
63cccae4 468
05c79b78
KZ
469static int
470do_swapon(const char *orig_special, int prio, int canonic) {
471 int status;
472 const char *special = orig_special;
473 int flags = 0;
63cccae4 474
05c79b78
KZ
475 if (verbose)
476 printf(_("%s on %s\n"), progname, orig_special);
477
478 if (!canonic) {
479 special = fsprobe_get_devname_by_spec(orig_special);
480 if (!special)
481 return cannot_find(orig_special);
63cccae4 482 }
ffa63a3d 483
05c79b78
KZ
484 if (swapon_checks(special))
485 return -1;
486
487#ifdef SWAP_FLAG_PREFER
488 if (prio >= 0) {
489 if (prio > SWAP_FLAG_PRIO_MASK)
490 prio = SWAP_FLAG_PRIO_MASK;
491 flags = SWAP_FLAG_PREFER
492 | ((prio & SWAP_FLAG_PRIO_MASK)
493 << SWAP_FLAG_PRIO_SHIFT);
494 }
495#endif
496 status = swapon(special, flags);
d51d05d3
KZ
497 if (status < 0)
498 warn(_("%s: swapon failed"), orig_special);
63cccae4
KZ
499
500 return status;
501}
502
503static int
756bfd01 504cannot_find(const char *special) {
d51d05d3 505 warnx(_("cannot find the device for %s"), special);
756bfd01
KZ
506 return -1;
507}
508
509static int
510swapon_by_label(const char *label, int prio) {
950f648f 511 const char *special = fsprobe_get_devname_by_label(label);
12ac2bbe 512 return special ? do_swapon(special, prio, CANONIC) : cannot_find(label);
756bfd01
KZ
513}
514
515static int
516swapon_by_uuid(const char *uuid, int prio) {
950f648f 517 const char *special = fsprobe_get_devname_by_uuid(uuid);
12ac2bbe 518 return special ? do_swapon(special, prio, CANONIC) : cannot_find(uuid);
756bfd01
KZ
519}
520
521static int
12ac2bbe
KZ
522do_swapoff(const char *orig_special, int quiet, int canonic) {
523 const char *special = orig_special;
756bfd01 524
63cccae4 525 if (verbose)
756bfd01
KZ
526 printf(_("%s on %s\n"), progname, orig_special);
527
12ac2bbe 528 if (!canonic) {
81772d3c 529 special = fsprobe_get_devname_by_spec(orig_special);
12ac2bbe
KZ
530 if (!special)
531 return cannot_find(orig_special);
532 }
63cccae4
KZ
533
534 if (swapoff(special) == 0)
535 return 0; /* success */
536
d51d05d3
KZ
537 if (errno == EPERM)
538 errx(EXIT_FAILURE, _("Not superuser."));
539
540 if (!quiet || errno == ENOMEM)
541 warn(_("%s: swapoff failed"), orig_special);
63cccae4 542
63cccae4
KZ
543 return -1;
544}
545
546static int
756bfd01 547swapoff_by_label(const char *label, int quiet) {
950f648f 548 const char *special = fsprobe_get_devname_by_label(label);
12ac2bbe 549 return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(label);
756bfd01
KZ
550}
551
552static int
553swapoff_by_uuid(const char *uuid, int quiet) {
950f648f 554 const char *special = fsprobe_get_devname_by_uuid(uuid);
12ac2bbe 555 return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(uuid);
756bfd01
KZ
556}
557
558static int
559swapon_all(void) {
63cccae4
KZ
560 FILE *fp;
561 struct mntent *fstab;
562 int status = 0;
63cccae4 563
756bfd01
KZ
564 read_proc_swaps();
565
4e270e3f 566 fp = setmntent(_PATH_MNTTAB, "r");
d51d05d3
KZ
567 if (fp == NULL)
568 err(2, _("%s: open failed"), _PATH_MNTTAB);
756bfd01
KZ
569
570 while ((fstab = getmntent(fp)) != NULL) {
756bfd01
KZ
571 const char *special;
572 int skip = 0;
573 int pri = priority;
1b414d89 574 char *opt, *opts;
756bfd01
KZ
575
576 if (!streq(fstab->mnt_type, MNTTYPE_SWAP))
577 continue;
578
1b414d89
KZ
579 opts = strdup(fstab->mnt_opts);
580
581 for (opt = strtok(opts, ","); opt != NULL;
582 opt = strtok(NULL, ",")) {
583 if (strncmp(opt, "pri=", 4) == 0)
584 pri = atoi(opt+4);
585 if (strcmp(opt, "noauto") == 0)
586 skip = 1;
587 }
588 free(opts);
589
590 if (skip)
591 continue;
592
81772d3c 593 special = fsprobe_get_devname_by_spec(fstab->mnt_fsname);
1b414d89
KZ
594 if (!special) {
595 if (!ifexists)
596 status |= cannot_find(fstab->mnt_fsname);
756bfd01 597 continue;
1b414d89 598 }
756bfd01
KZ
599
600 if (!is_in_proc_swaps(special) &&
1b414d89
KZ
601 (!ifexists || !access(special, R_OK)))
602 status |= do_swapon(special, pri, CANONIC);
603
604 free((void *) special);
756bfd01
KZ
605 }
606 fclose(fp);
607
608 return status;
609}
610
611static const char **llist = NULL;
612static int llct = 0;
613static const char **ulist = NULL;
614static int ulct = 0;
615
616static void addl(const char *label) {
81772d3c
KZ
617 llist = (const char **) realloc(llist, (++llct) * sizeof(char *));
618 if (!llist)
619 exit(EXIT_FAILURE);
756bfd01
KZ
620 llist[llct-1] = label;
621}
622
623static void addu(const char *uuid) {
81772d3c
KZ
624 ulist = (const char **) realloc(ulist, (++ulct) * sizeof(char *));
625 if (!ulist)
626 exit(EXIT_FAILURE);
756bfd01
KZ
627 ulist[ulct-1] = uuid;
628}
629
630static int
631main_swapon(int argc, char *argv[]) {
632 int status = 0;
633 int c, i;
634
0d761944 635 while ((c = getopt_long(argc, argv, "ahefp:svVL:U:",
756bfd01 636 longswaponopts, NULL)) != -1) {
63cccae4
KZ
637 switch (c) {
638 case 'a': /* all */
639 ++all;
640 break;
641 case 'h': /* help */
642 swapon_usage(stdout, 0);
643 break;
644 case 'p': /* priority */
645 priority = atoi(optarg);
646 break;
756bfd01
KZ
647 case 'L':
648 addl(optarg);
649 break;
650 case 'U':
651 addu(optarg);
652 break;
95f1bdee
KZ
653 case 'e': /* ifexists */
654 ifexists = 1;
655 break;
0d761944
KZ
656 case 'f':
657 fixpgsz = 1;
658 break;
63cccae4
KZ
659 case 's': /* status report */
660 status = display_summary();
661 exit(status);
662 case 'v': /* be chatty */
663 ++verbose;
664 break;
665 case 'V': /* version */
baf39af1 666 printf("%s: (%s)\n", progname, PACKAGE_STRING);
63cccae4
KZ
667 exit(0);
668 case 0:
669 break;
670 case '?':
671 default:
672 swapon_usage(stderr, 1);
673 }
674 }
675 argv += optind;
676
756bfd01 677 if (!all && !llct && !ulct && *argv == NULL)
63cccae4
KZ
678 swapon_usage(stderr, 2);
679
756bfd01
KZ
680 if (ifexists && (!all || strcmp(progname, "swapon")))
681 swapon_usage(stderr, 1);
95f1bdee 682
756bfd01
KZ
683 if (all)
684 status |= swapon_all();
63cccae4 685
756bfd01
KZ
686 for (i = 0; i < llct; i++)
687 status |= swapon_by_label(llist[i], priority);
63cccae4 688
756bfd01
KZ
689 for (i = 0; i < ulct; i++)
690 status |= swapon_by_uuid(ulist[i], priority);
63cccae4
KZ
691
692 while (*argv != NULL)
12ac2bbe 693 status |= do_swapon(*argv++, priority, !CANONIC);
63cccae4
KZ
694
695 return status;
696}
697
698static int
699main_swapoff(int argc, char *argv[]) {
700 FILE *fp;
701 struct mntent *fstab;
702 int status = 0;
703 int c, i;
704
756bfd01 705 while ((c = getopt_long(argc, argv, "ahvVL:U:",
63cccae4
KZ
706 longswapoffopts, NULL)) != -1) {
707 switch (c) {
708 case 'a': /* all */
709 ++all;
710 break;
711 case 'h': /* help */
712 swapoff_usage(stdout, 0);
713 break;
714 case 'v': /* be chatty */
715 ++verbose;
716 break;
717 case 'V': /* version */
baf39af1 718 printf("%s (%s)\n", progname, PACKAGE_STRING);
63cccae4 719 exit(0);
756bfd01
KZ
720 case 'L':
721 addl(optarg);
722 break;
723 case 'U':
724 addu(optarg);
725 break;
63cccae4
KZ
726 case 0:
727 break;
728 case '?':
729 default:
730 swapoff_usage(stderr, 1);
731 }
732 }
733 argv += optind;
734
756bfd01 735 if (!all && !llct && !ulct && *argv == NULL)
63cccae4
KZ
736 swapoff_usage(stderr, 2);
737
738 /*
739 * swapoff any explicitly given arguments.
740 * Complain in case the swapoff call fails.
741 */
756bfd01
KZ
742 for (i = 0; i < llct; i++)
743 status |= swapoff_by_label(llist[i], !QUIET);
744
745 for (i = 0; i < ulct; i++)
746 status |= swapoff_by_uuid(ulist[i], !QUIET);
747
63cccae4 748 while (*argv != NULL)
12ac2bbe 749 status |= do_swapoff(*argv++, !QUIET, !CANONIC);
63cccae4
KZ
750
751 if (all) {
752 /*
a47f2e66 753 * In case /proc/swaps exists, unswap stuff listed there.
63cccae4
KZ
754 * We are quiet but report errors in status.
755 * Errors might mean that /proc/swaps
756 * exists as ordinary file, not in procfs.
757 * do_swapoff() exits immediately on EPERM.
758 */
759 read_proc_swaps();
760 for(i=0; i<numSwaps; i++)
12ac2bbe 761 status |= do_swapoff(swapFiles[i], QUIET, CANONIC);
63cccae4
KZ
762
763 /*
a47f2e66 764 * Unswap stuff mentioned in /etc/fstab.
63cccae4
KZ
765 * Probably it was unmounted already, so errors are not bad.
766 * Doing swapoff -a twice should not give error messages.
767 */
4e270e3f 768 fp = setmntent(_PATH_MNTTAB, "r");
d51d05d3
KZ
769 if (fp == NULL)
770 err(2, _("%s: open failed"), _PATH_MNTTAB);
771
63cccae4 772 while ((fstab = getmntent(fp)) != NULL) {
4ee7bde1
LJ
773 const char *special;
774
775 if (!streq(fstab->mnt_type, MNTTYPE_SWAP))
776 continue;
777
81772d3c 778 special = fsprobe_get_devname_by_spec(fstab->mnt_fsname);
4ee7bde1
LJ
779 if (!special)
780 continue;
781
782 if (!is_in_proc_swaps(special))
12ac2bbe 783 do_swapoff(special, QUIET, CANONIC);
63cccae4 784 }
c129767e 785 fclose(fp);
63cccae4
KZ
786 }
787
788 return status;
789}
790
791int
792main(int argc, char *argv[]) {
63cccae4
KZ
793
794 setlocale(LC_ALL, "");
795 bindtextdomain(PACKAGE, LOCALEDIR);
796 textdomain(PACKAGE);
797
d51d05d3
KZ
798 progname = program_invocation_short_name;
799 if (!progname) {
800 char *p = strrchr(argv[0], '/');
801 progname = p ? p+1 : argv[0];
802 }
63cccae4 803
756bfd01 804 if (streq(progname, "swapon"))
63cccae4 805 return main_swapon(argc, argv);
01373d74 806 else if (streq(progname, "swapoff"))
63cccae4 807 return main_swapoff(argc, argv);
01373d74
KZ
808
809 errx(EXIT_FAILURE, _("'%s' is unsupported program name "
810 "(must be 'swapon' or 'swapoff')."), progname);
6dbe3af9 811}