]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/swapon.c
last: mention optional arguments in usage
[thirdparty/util-linux.git] / sys-utils / swapon.c
CommitLineData
e076b552 1#include <assert.h>
fd6b7a7f
KZ
2#include <stdlib.h>
3#include <stdio.h>
4#include <getopt.h>
5#include <string.h>
fd6b7a7f 6#include <errno.h>
5c36a0eb 7#include <sys/stat.h>
ffa63a3d 8#include <unistd.h>
6274b987
KC
9#include <sys/types.h>
10#include <sys/wait.h>
11#include <fcntl.h>
3399a218 12#include <stdint.h>
57a60bf0 13#include <ctype.h>
81772d3c 14
64b58881 15#include <libmount.h>
b5b2c388 16
d335c9bd
KZ
17#include "c.h"
18#include "nls.h"
3399a218
MK
19#include "bitops.h"
20#include "blkdev.h"
4e270e3f 21#include "pathnames.h"
bfbb12d2 22#include "xalloc.h"
efb8854f 23#include "closestream.h"
167eaed7 24
d335c9bd 25#include "swapheader.h"
0b0c231f 26#include "swapon-common.h"
e076b552
SK
27#include "strutils.h"
28#include "tt.h"
0b0c231f 29
6274b987
KC
30#define PATH_MKSWAP "/sbin/mkswap"
31
ffa63a3d
MF
32#ifdef HAVE_SYS_SWAP_H
33# include <sys/swap.h>
34#endif
35
c2301380
HD
36#ifndef SWAP_FLAG_DISCARD
37# define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */
38#endif
39
9514a612
KZ
40#ifndef SWAP_FLAG_PREFER
41# define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
42#endif
43
44#ifndef SWAP_FLAG_PRIO_MASK
45# define SWAP_FLAG_PRIO_MASK 0x7fff
46#endif
47
48#ifndef SWAP_FLAG_PRIO_SHIFT
49# define SWAP_FLAG_PRIO_SHIFT 0
50#endif
51
ffa63a3d
MF
52#ifndef SWAPON_HAS_TWO_ARGS
53/* libc is insane, let's call the kernel */
54# include <sys/syscall.h>
55# define swapon(path, flags) syscall(SYS_swapon, path, flags)
ffa63a3d
MF
56#endif
57
63cccae4 58#define QUIET 1
12ac2bbe 59#define CANONIC 1
63cccae4 60
3399a218
MK
61#define MAX_PAGESIZE (64 * 1024)
62
e8be80dd
KZ
63enum {
64 SIG_SWAPSPACE = 1,
65 SIG_SWSUSPEND
66};
67
617d8a3b
KZ
68#define SWAP_SIGNATURE "SWAPSPACE2"
69#define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
70
16ff9813
TK
71static int all;
72static int priority = -1; /* non-prioritized swap by default */
73static int discard;
6dbe3af9 74
95f1bdee 75/* If true, don't complain if the device/file doesn't exist */
16ff9813
TK
76static int ifexists;
77static int fixpgsz;
16ff9813 78static int verbose;
95f1bdee 79
e076b552
SK
80/* column names */
81struct colinfo {
82 const char *name; /* header */
83 double whint; /* width hint (N < 1 is in percent of termwidth) */
84 int flags; /* TT_FL_* */
85 const char *help;
86};
87enum { COL_PATH, COL_TYPE, COL_SIZE, COL_USED, COL_PRIO };
88struct colinfo infos[] = {
89 [COL_PATH] = { "NAME", 0.20, 0, N_("device file or partition path") },
90 [COL_TYPE] = { "TYPE", 0.20, TT_FL_TRUNC, N_("type of the device")},
91 [COL_SIZE] = { "SIZE", 0.20, TT_FL_RIGHT, N_("size of the swap area")},
92 [COL_USED] = { "USED", 0.20, TT_FL_RIGHT, N_("bytes in use")},
93 [COL_PRIO] = { "PRIO", 0.20, TT_FL_RIGHT, N_("swap priority")},
94};
95#define NCOLS ARRAY_SIZE(infos)
96static int columns[NCOLS], ncolumns;
97
98static int column_name_to_id(const char *name, size_t namesz)
99{
100 size_t i;
101
102 assert(name);
103
104 for (i = 0; i < NCOLS; i++) {
105 const char *cn = infos[i].name;
106
107 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
108 return i;
109 }
110 warnx(_("unknown column: %s"), name);
111 return -1;
112}
113
114static inline int get_column_id(int num)
115{
116 assert(ARRAY_SIZE(columns) == NCOLS);
117 assert(num < ncolumns);
118 assert(columns[num] < (int)NCOLS);
119
120 return columns[num];
121}
122
123static inline struct colinfo *get_column_info(unsigned num)
124{
125 return &infos[get_column_id(num)];
126}
127
7ae8b469 128static void add_tt_line(struct tt *tt, struct libmnt_fs *fs, int bytes)
e076b552
SK
129{
130 int i;
131 struct tt_line *line;
132
133 assert(tt);
134 assert(fs);
135
136 line = tt_add_line(tt, NULL);
137 if (!line) {
138 warn(_("failed to add line to output"));
139 return;
140 }
141
142 for (i = 0; i < ncolumns; i++) {
143 char *str = NULL;
7ae8b469 144 off_t size;
e076b552
SK
145
146 switch (get_column_id(i)) {
147 case COL_PATH:
a0e35e30 148 xasprintf(&str, "%s", mnt_fs_get_source(fs));
e076b552
SK
149 break;
150 case COL_TYPE:
a0e35e30 151 xasprintf(&str, "%s", mnt_fs_get_swaptype(fs));
e076b552
SK
152 break;
153 case COL_SIZE:
7ae8b469
SK
154 size = mnt_fs_get_size(fs);
155 size *= 1024; /* convert to bytes */
156 if (bytes)
a0e35e30 157 xasprintf(&str, "%jd", size);
7ae8b469
SK
158 else
159 str = size_to_human_string(SIZE_SUFFIX_1LETTER, size);
e076b552
SK
160 break;
161 case COL_USED:
7ae8b469
SK
162 size = mnt_fs_get_usedsize(fs);
163 size *= 1024; /* convert to bytes */
164 if (bytes)
a0e35e30 165 xasprintf(&str, "%jd", size);
7ae8b469
SK
166 else
167 str = size_to_human_string(SIZE_SUFFIX_1LETTER, size);
e076b552
SK
168 break;
169 case COL_PRIO:
a0e35e30 170 xasprintf(&str, "%d", mnt_fs_get_priority(fs));
e076b552
SK
171 break;
172 default:
173 break;
174 }
175
a0e35e30 176 if (str)
e076b552
SK
177 tt_line_set_data(line, i, str);
178 }
179 return;
180}
181
d335c9bd 182static int display_summary(void)
fd6b7a7f 183{
5072b90a 184 struct libmnt_table *st = get_swaps();
64b58881
KZ
185 struct libmnt_iter *itr;
186 struct libmnt_fs *fs;
fd6b7a7f 187
64b58881 188 if (!st)
57a60bf0 189 return -1;
e8f26419 190
a2f17bb2
KZ
191 if (mnt_table_is_empty(st))
192 return 0;
193
64b58881
KZ
194 itr = mnt_new_iter(MNT_ITER_FORWARD);
195 if (!itr)
196 err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
57a60bf0 197
a2f17bb2 198 printf(_("%s\t\t\t\tType\t\tSize\tUsed\tPriority\n"), _("Filename"));
64b58881
KZ
199
200 while (mnt_table_next_fs(st, itr, &fs) == 0) {
201 printf("%-39s\t%s\t%jd\t%jd\t%d\n",
202 mnt_fs_get_source(fs),
203 mnt_fs_get_swaptype(fs),
204 mnt_fs_get_size(fs),
205 mnt_fs_get_usedsize(fs),
206 mnt_fs_get_priority(fs));
57a60bf0 207 }
fd6b7a7f 208
64b58881
KZ
209 mnt_free_iter(itr);
210 return 0;
fd6b7a7f
KZ
211}
212
7ae8b469 213static int show_table(int tt_flags, int bytes)
e076b552
SK
214{
215 struct libmnt_table *st = get_swaps();
880f09c8 216 struct libmnt_iter *itr = NULL;
e076b552
SK
217 struct libmnt_fs *fs;
218
219 int i, rc = 0;
880f09c8 220 struct tt *tt = NULL;
e076b552
SK
221
222 if (!st)
223 return -1;
224
225 itr = mnt_new_iter(MNT_ITER_FORWARD);
226 if (!itr)
227 err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
228
229 tt = tt_new_table(tt_flags);
230 if (!tt) {
231 warn(_("failed to initialize output table"));
880f09c8 232 goto done;
e076b552
SK
233 }
234
235 for (i = 0; i < ncolumns; i++) {
236 struct colinfo *col = get_column_info(i);
237
238 if (!tt_define_column(tt, col->name, col->whint, col->flags)) {
239 warnx(_("failed to initialize output column"));
240 rc = -1;
241 goto done;
242 }
243 }
244
245 while (mnt_table_next_fs(st, itr, &fs) == 0)
7ae8b469 246 add_tt_line(tt, fs, bytes);
e076b552 247
e076b552
SK
248 tt_print_table(tt);
249 done:
880f09c8 250 mnt_free_iter(itr);
e076b552
SK
251 tt_free_table(tt);
252 return rc;
253}
254
6274b987 255/* calls mkswap */
d335c9bd
KZ
256static int swap_reinitialize(const char *device,
257 const char *label, const char *uuid)
b5b2c388 258{
6274b987
KC
259 pid_t pid;
260 int status, ret;
261 char *cmd[7];
262 int idx=0;
263
0d761944
KZ
264 warnx(_("%s: reinitializing the swap."), device);
265
6274b987
KC
266 switch((pid=fork())) {
267 case -1: /* fork error */
d51d05d3 268 warn(_("fork failed"));
6274b987
KC
269 return -1;
270
271 case 0: /* child */
272 cmd[idx++] = PATH_MKSWAP;
273 if (label && *label) {
274 cmd[idx++] = "-L";
275 cmd[idx++] = (char *) label;
276 }
277 if (uuid && *uuid) {
278 cmd[idx++] = "-U";
279 cmd[idx++] = (char *) uuid;
280 }
281 cmd[idx++] = (char *) device;
282 cmd[idx++] = NULL;
283 execv(cmd[0], cmd);
07ff972e 284 err(EXIT_FAILURE, _("failed to execute %s"), cmd[0]);
6274b987
KC
285
286 default: /* parent */
287 do {
288 if ((ret = waitpid(pid, &status, 0)) < 0
289 && errno == EINTR)
290 continue;
291 else if (ret < 0) {
d51d05d3 292 warn(_("waitpid failed"));
6274b987
KC
293 return -1;
294 }
295 } while (0);
296
297 /* mkswap returns: 0=suss, 1=error */
298 if (WIFEXITED(status) && WEXITSTATUS(status)==0)
299 return 0; /* ok */
f8ff4ebb 300 break;
6274b987
KC
301 }
302 return -1; /* error */
303}
304
d335c9bd 305static int swap_rewrite_signature(const char *devname, unsigned int pagesize)
617d8a3b
KZ
306{
307 int fd, rc = -1;
308
309 fd = open(devname, O_WRONLY);
310 if (fd == -1) {
289dcc90 311 warn(_("cannot open %s"), devname);
617d8a3b
KZ
312 return -1;
313 }
314
5dd53f43
KZ
315 if (lseek(fd, pagesize - SWAP_SIGNATURE_SZ, SEEK_SET) < 0) {
316 warn(_("%s: lseek failed"), devname);
617d8a3b 317 goto err;
5dd53f43 318 }
617d8a3b
KZ
319
320 if (write(fd, (void *) SWAP_SIGNATURE,
5dd53f43
KZ
321 SWAP_SIGNATURE_SZ) != SWAP_SIGNATURE_SZ) {
322 warn(_("%s: write signature failed"), devname);
617d8a3b 323 goto err;
5dd53f43 324 }
617d8a3b
KZ
325
326 rc = 0;
327err:
14699715
SK
328 if (close_fd(fd) != 0) {
329 warn(_("write failed: %s"), devname);
330 rc = -1;
331 }
617d8a3b
KZ
332 return rc;
333}
334
d335c9bd 335static int swap_detect_signature(const char *buf, int *sig)
3399a218 336{
e8be80dd
KZ
337 if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
338 memcmp(buf, "SWAPSPACE2", 10) == 0)
339 *sig = SIG_SWAPSPACE;
340
341 else if (memcmp(buf, "S1SUSPEND", 9) == 0 ||
342 memcmp(buf, "S2SUSPEND", 9) == 0 ||
343 memcmp(buf, "ULSUSPEND", 9) == 0 ||
5a16af58
KZ
344 memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0 ||
345 memcmp(buf, "LINHIB0001", 10) == 0)
e8be80dd
KZ
346 *sig = SIG_SWSUSPEND;
347 else
348 return 0;
3399a218 349
e8be80dd 350 return 1;
3399a218
MK
351}
352
d335c9bd 353static char *swap_get_header(int fd, int *sig, unsigned int *pagesize)
3399a218 354{
3399a218 355 char *buf;
e8be80dd
KZ
356 ssize_t datasz;
357 unsigned int page;
3399a218 358
e8be80dd
KZ
359 *pagesize = 0;
360 *sig = 0;
3399a218 361
bfbb12d2 362 buf = xmalloc(MAX_PAGESIZE);
3399a218
MK
363
364 datasz = read(fd, buf, MAX_PAGESIZE);
e8be80dd
KZ
365 if (datasz == (ssize_t) -1)
366 goto err;
3399a218
MK
367
368 for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) {
369 /* skip 32k pagesize since this does not seem to
370 * be supported */
371 if (page == 0x8000)
372 continue;
373 /* the smallest swap area is PAGE_SIZE*10, it means
374 * 40k, that's less than MAX_PAGESIZE */
24f010e8 375 if (datasz < 0 || (size_t) datasz < (page - SWAP_SIGNATURE_SZ))
3399a218 376 break;
617d8a3b 377 if (swap_detect_signature(buf + page - SWAP_SIGNATURE_SZ, sig)) {
e8be80dd 378 *pagesize = page;
3399a218
MK
379 break;
380 }
381 }
382
e8be80dd
KZ
383 if (*pagesize)
384 return buf;
3399a218 385err:
e8be80dd
KZ
386 free(buf);
387 return NULL;
388}
389
390/* returns real size of swap space */
d335c9bd
KZ
391static unsigned long long swap_get_size(const char *hdr, const char *devname,
392 unsigned int pagesize)
e8be80dd
KZ
393{
394 unsigned int last_page = 0;
395 int swap_version = 0;
396 int flip = 0;
397 struct swap_header_v1_2 *s;
398
399 s = (struct swap_header_v1_2 *) hdr;
400 if (s->version == 1) {
401 swap_version = 1;
402 last_page = s->last_page;
403 } else if (swab32(s->version) == 1) {
404 flip = 1;
405 swap_version = 1;
406 last_page = swab32(s->last_page);
407 }
408 if (verbose)
04c94441
KZ
409 warnx(_("%s: found swap signature: version %d, "
410 "page-size %d, %s byte order"),
e8be80dd 411 devname,
e8be80dd 412 swap_version,
04c94441
KZ
413 pagesize / 1024,
414 flip ? _("different") : _("same"));
e8be80dd 415
98e9ff61 416 return ((unsigned long long) last_page + 1) * pagesize;
3399a218
MK
417}
418
d335c9bd 419static void swap_get_info(const char *hdr, char **label, char **uuid)
b5b2c388
KZ
420{
421 struct swap_header_v1_2 *s = (struct swap_header_v1_2 *) hdr;
422
423 if (s && *s->volume_name && label)
424 *label = xstrdup(s->volume_name);
425
426 if (s && *s->uuid && uuid) {
427 const unsigned char *u = s->uuid;
428 char str[37];
429
430 snprintf(str, sizeof(str),
431 "%02x%02x%02x%02x-"
432 "%02x%02x-%02x%02x-"
433 "%02x%02x-%02x%02x%02x%02x%02x%02x",
434 u[0], u[1], u[2], u[3],
435 u[4], u[5], u[6], u[7],
436 u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]);
437 *uuid = xstrdup(str);
438 }
439}
440
d335c9bd 441static int swapon_checks(const char *special)
05c79b78 442{
63cccae4 443 struct stat st;
05c79b78
KZ
444 int fd = -1, sig;
445 char *hdr = NULL;
e8be80dd
KZ
446 unsigned int pagesize;
447 unsigned long long devsize = 0;
cd04b26b 448 int permMask;
63cccae4 449
63cccae4 450 if (stat(special, &st) < 0) {
add1b8af 451 warn(_("stat failed %s"), special);
05c79b78 452 goto err;
63cccae4
KZ
453 }
454
cd04b26b
KZ
455 permMask = S_ISBLK(st.st_mode) ? 07007 : 07077;
456 if ((st.st_mode & permMask) != 0)
457 warnx(_("%s: insecure permissions %04o, %04o suggested."),
d51d05d3 458 special, st.st_mode & 07777,
88530f9f 459 ~permMask & 0666);
306c1df2 460
cd04b26b
KZ
461 if (S_ISREG(st.st_mode) && st.st_uid != 0)
462 warnx(_("%s: insecure file owner %d, 0 (root) suggested."),
306c1df2 463 special, st.st_uid);
88530f9f
KZ
464
465 /* test for holes by LBT */
466 if (S_ISREG(st.st_mode)) {
467 if (st.st_blocks * 512 < st.st_size) {
d51d05d3
KZ
468 warnx(_("%s: skipping - it appears to have holes."),
469 special);
05c79b78 470 goto err;
88530f9f 471 }
e8be80dd
KZ
472 devsize = st.st_size;
473 }
474
475 fd = open(special, O_RDONLY);
476 if (fd == -1) {
289dcc90 477 warn(_("cannot open %s"), special);
05c79b78 478 goto err;
e8be80dd
KZ
479 }
480
05c79b78
KZ
481 if (S_ISBLK(st.st_mode) && blkdev_get_size(fd, &devsize)) {
482 warn(_("%s: get size failed"), special);
483 goto err;
e8be80dd
KZ
484 }
485
486 hdr = swap_get_header(fd, &sig, &pagesize);
487 if (!hdr) {
d51d05d3 488 warn(_("%s: read swap header failed"), special);
05c79b78 489 goto err;
88530f9f
KZ
490 }
491
e8be80dd
KZ
492 if (sig == SIG_SWAPSPACE && pagesize) {
493 unsigned long long swapsize =
494 swap_get_size(hdr, special, pagesize);
24f010e8
KZ
495 int syspg = getpagesize();
496
3399a218 497 if (verbose)
e6b0611b 498 warnx(_("%s: pagesize=%d, swapsize=%llu, devsize=%llu"),
e8be80dd
KZ
499 special, pagesize, swapsize, devsize);
500
501 if (swapsize > devsize) {
502 if (verbose)
d51d05d3
KZ
503 warnx(_("%s: last_page 0x%08llx is larger"
504 " than actual size of swapspace"),
e8be80dd 505 special, swapsize);
24f010e8 506 } else if (syspg < 0 || (unsigned) syspg != pagesize) {
0d761944 507 if (fixpgsz) {
b5b2c388
KZ
508 char *label = NULL, *uuid = NULL;
509 int rc;
510
511 swap_get_info(hdr, &label, &uuid);
512
93bfcc94 513 warnx(_("%s: swap format pagesize does not match."),
0d761944 514 special);
b5b2c388
KZ
515 rc = swap_reinitialize(special, label, uuid);
516 free(label);
517 free(uuid);
518 if (rc < 0)
0d761944
KZ
519 goto err;
520 } else
93bfcc94
KZ
521 warnx(_("%s: swap format pagesize does not match. "
522 "(Use --fixpgsz to reinitialize it.)"),
0d761944 523 special);
e8be80dd
KZ
524 }
525 } else if (sig == SIG_SWSUSPEND) {
526 /* We have to reinitialize swap with old (=useless) software suspend
527 * data. The problem is that if we don't do it, then we get data
528 * corruption the next time an attempt at unsuspending is made.
529 */
d51d05d3 530 warnx(_("%s: software suspend data detected. "
617d8a3b 531 "Rewriting the swap signature."),
d51d05d3 532 special);
617d8a3b 533 if (swap_rewrite_signature(special, pagesize) < 0)
05c79b78 534 goto err;
6274b987
KC
535 }
536
05c79b78
KZ
537 free(hdr);
538 close(fd);
539 return 0;
05c79b78
KZ
540err:
541 if (fd != -1)
542 close(fd);
543 free(hdr);
544 return -1;
545}
63cccae4 546
d335c9bd
KZ
547static int do_swapon(const char *orig_special, int prio,
548 int fl_discard, int canonic)
549{
05c79b78
KZ
550 int status;
551 const char *special = orig_special;
552 int flags = 0;
63cccae4 553
05c79b78 554 if (verbose)
d9f07b10 555 printf(_("swapon %s\n"), orig_special);
05c79b78
KZ
556
557 if (!canonic) {
e5157fc9 558 special = mnt_resolve_spec(orig_special, mntcache);
05c79b78
KZ
559 if (!special)
560 return cannot_find(orig_special);
63cccae4 561 }
ffa63a3d 562
05c79b78
KZ
563 if (swapon_checks(special))
564 return -1;
565
566#ifdef SWAP_FLAG_PREFER
567 if (prio >= 0) {
568 if (prio > SWAP_FLAG_PRIO_MASK)
569 prio = SWAP_FLAG_PRIO_MASK;
570 flags = SWAP_FLAG_PREFER
571 | ((prio & SWAP_FLAG_PRIO_MASK)
572 << SWAP_FLAG_PRIO_SHIFT);
573 }
574#endif
c2301380
HD
575 if (fl_discard)
576 flags |= SWAP_FLAG_DISCARD;
577
05c79b78 578 status = swapon(special, flags);
d51d05d3
KZ
579 if (status < 0)
580 warn(_("%s: swapon failed"), orig_special);
63cccae4
KZ
581
582 return status;
583}
584
d335c9bd
KZ
585static int swapon_by_label(const char *label, int prio, int dsc)
586{
e5157fc9 587 const char *special = mnt_resolve_tag("LABEL", label, mntcache);
c2301380
HD
588 return special ? do_swapon(special, prio, dsc, CANONIC) :
589 cannot_find(label);
756bfd01
KZ
590}
591
d335c9bd
KZ
592static int swapon_by_uuid(const char *uuid, int prio, int dsc)
593{
e5157fc9 594 const char *special = mnt_resolve_tag("UUID", uuid, mntcache);
c2301380
HD
595 return special ? do_swapon(special, prio, dsc, CANONIC) :
596 cannot_find(uuid);
756bfd01
KZ
597}
598
d335c9bd
KZ
599static int swapon_all(void)
600{
5072b90a
KZ
601 struct libmnt_table *tb = get_fstab();
602 struct libmnt_iter *itr;
603 struct libmnt_fs *fs;
63cccae4 604 int status = 0;
63cccae4 605
5072b90a 606 if (!tb)
d335c9bd 607 err(EXIT_FAILURE, _("failed to parse %s"), mnt_get_fstab_path());
756bfd01 608
5072b90a
KZ
609 itr = mnt_new_iter(MNT_ITER_FORWARD);
610 if (!itr)
611 err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
756bfd01 612
5072b90a
KZ
613 while (mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) {
614 /* defaults */
615 int pri = priority, dsc = discard, nofail = ifexists;
616 char *p, *src;
1b414d89 617
5072b90a 618 if (mnt_fs_get_option(fs, "noauto", NULL, NULL) == 0)
1b414d89 619 continue;
5072b90a
KZ
620 if (mnt_fs_get_option(fs, "discard", NULL, NULL) == 0)
621 dsc = 1;
622 if (mnt_fs_get_option(fs, "nofail", NULL, NULL) == 0)
623 nofail = 1;
624 if (mnt_fs_get_option(fs, "pri", &p, NULL) == 0 && p)
625 pri = atoi(p);
626
627 src = mnt_resolve_spec(mnt_fs_get_source(fs), mntcache);
628 if (!src) {
a5fd3d68 629 if (!nofail)
5072b90a 630 status |= cannot_find(mnt_fs_get_source(fs));
756bfd01 631 continue;
1b414d89 632 }
756bfd01 633
5072b90a
KZ
634 if (!is_active_swap(src) &&
635 (!nofail || !access(src, R_OK)))
636 status |= do_swapon(src, pri, dsc, CANONIC);
756bfd01 637 }
756bfd01 638
5072b90a 639 mnt_free_iter(itr);
756bfd01
KZ
640 return status;
641}
642
8b0d5341
KZ
643static void __attribute__ ((__noreturn__)) usage(FILE * out)
644{
e09bd8d0 645 size_t i;
8b0d5341
KZ
646 fputs(USAGE_HEADER, out);
647
648 fprintf(out, _(" %s [options] [<spec>]\n"), program_invocation_short_name);
649
650 fputs(USAGE_OPTIONS, out);
651 fputs(_(" -a, --all enable all swaps from /etc/fstab\n"
652 " -d, --discard discard freed pages before they are reused\n"
59114ba3 653 " -e, --ifexists silently skip devices that do not exist\n"
8b0d5341
KZ
654 " -f, --fixpgsz reinitialize the swap space if necessary\n"
655 " -p, --priority <prio> specify the priority of the swap device\n"
e076b552
SK
656 " -s, --summary display summary about used swap devices\n"
657 " --show[=<columns>] display summary in definable table\n"
658 " --noheadings don't print headings, use with --show\n"
659 " --raw use the raw output format, use with --show\n"
7ae8b469 660 " --bytes display swap size in bytes in --show output\n"
8b0d5341
KZ
661 " -v, --verbose verbose mode\n"), out);
662
663 fputs(USAGE_SEPARATOR, out);
664 fputs(USAGE_HELP, out);
665 fputs(USAGE_VERSION, out);
666
667 fputs(_("\nThe <spec> parameter:\n" \
9f9d0f21
KZ
668 " -L <label> synonym for LABEL=<label>\n"
669 " -U <uuid> synonym for UUID=<uuid>\n"
670 " LABEL=<label> specifies device by swap area label\n"
671 " UUID=<uuid> specifies device by swap area UUID\n"
672 " PARTLABEL=<label> specifies device by partition label\n"
673 " PARTUUID=<uuid> specifies device by partition UUID\n"
674 " <device> name of device to be used\n"
8b0d5341
KZ
675 " <file> name of file to be used\n"), out);
676
e076b552 677 fputs(_("\nAvailable columns (for --show):\n"), out);
e09bd8d0 678 for (i = 0; i < NCOLS; i++)
e076b552
SK
679 fprintf(out, " %4s %s\n", infos[i].name, _(infos[i].help));
680
8b0d5341
KZ
681 fprintf(out, USAGE_MAN_TAIL("swapon(8)"));
682 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
683}
684
d9f07b10
KZ
685int main(int argc, char *argv[])
686{
8b0d5341 687 int status = 0, c;
e076b552 688 int show = 0, tt_flags = 0;
7ae8b469 689 int bytes = 0;
0b0c231f 690 size_t i;
756bfd01 691
e076b552
SK
692 enum {
693 SHOW_OPTION = CHAR_MAX + 1,
694 RAW_OPTION,
7ae8b469
SK
695 NOHEADINGS_OPTION,
696 BYTES_OPTION
e076b552
SK
697 };
698
8b0d5341
KZ
699 static const struct option long_opts[] = {
700 { "priority", 1, 0, 'p' },
701 { "discard", 0, 0, 'd' },
702 { "ifexists", 0, 0, 'e' },
703 { "summary", 0, 0, 's' },
704 { "fixpgsz", 0, 0, 'f' },
705 { "all", 0, 0, 'a' },
706 { "help", 0, 0, 'h' },
707 { "verbose", 0, 0, 'v' },
708 { "version", 0, 0, 'V' },
e076b552
SK
709 { "show", 2, 0, SHOW_OPTION },
710 { "noheadings", 0, 0, NOHEADINGS_OPTION },
711 { "raw", 0, 0, RAW_OPTION },
7ae8b469 712 { "bytes", 0, 0, BYTES_OPTION },
8b0d5341
KZ
713 { NULL, 0, 0, 0 }
714 };
715
d9f07b10
KZ
716 setlocale(LC_ALL, "");
717 bindtextdomain(PACKAGE, LOCALEDIR);
718 textdomain(PACKAGE);
719 atexit(close_stdout);
720
721 mnt_init_debug(0);
722 mntcache = mnt_new_cache();
723
c2301380 724 while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:",
8b0d5341 725 long_opts, NULL)) != -1) {
63cccae4
KZ
726 switch (c) {
727 case 'a': /* all */
728 ++all;
729 break;
730 case 'h': /* help */
8b0d5341 731 usage(stdout);
63cccae4
KZ
732 break;
733 case 'p': /* priority */
9db6a749
SK
734 priority = strtos16_or_err(optarg,
735 _("failed to parse priority"));
63cccae4 736 break;
756bfd01 737 case 'L':
0b0c231f 738 add_label(optarg);
756bfd01
KZ
739 break;
740 case 'U':
0b0c231f 741 add_uuid(optarg);
756bfd01 742 break;
c2301380
HD
743 case 'd':
744 discard = 1;
745 break;
95f1bdee
KZ
746 case 'e': /* ifexists */
747 ifexists = 1;
748 break;
0d761944
KZ
749 case 'f':
750 fixpgsz = 1;
751 break;
63cccae4
KZ
752 case 's': /* status report */
753 status = display_summary();
8b0d5341 754 return status;
63cccae4
KZ
755 case 'v': /* be chatty */
756 ++verbose;
757 break;
e076b552
SK
758 case SHOW_OPTION:
759 if (optarg) {
760 ncolumns = string_to_idarray(optarg,
761 columns,
762 ARRAY_SIZE(columns),
763 column_name_to_id);
764 if (ncolumns < 0)
765 return EXIT_FAILURE;
766 }
767 show = 1;
768 break;
769 case NOHEADINGS_OPTION:
770 tt_flags |= TT_FL_NOHEADINGS;
771 break;
772 case RAW_OPTION:
773 tt_flags |= TT_FL_RAW;
774 break;
7ae8b469
SK
775 case BYTES_OPTION:
776 bytes = 1;
777 break;
63cccae4 778 case 'V': /* version */
d9f07b10
KZ
779 printf(UTIL_LINUX_VERSION);
780 return EXIT_SUCCESS;
63cccae4
KZ
781 case 0:
782 break;
783 case '?':
784 default:
8b0d5341 785 usage(stderr);
63cccae4
KZ
786 }
787 }
788 argv += optind;
789
d96b743f 790 if (show || (!all && !numof_labels() && !numof_uuids() && *argv == NULL)) {
e076b552
SK
791 if (!ncolumns) {
792 /* default columns */
793 columns[ncolumns++] = COL_PATH;
794 columns[ncolumns++] = COL_TYPE;
795 columns[ncolumns++] = COL_SIZE;
796 columns[ncolumns++] = COL_USED;
797 columns[ncolumns++] = COL_PRIO;
798 }
7ae8b469 799 status = show_table(tt_flags, bytes);
e076b552
SK
800 return status;
801 }
802
d9f07b10 803 if (ifexists && !all)
8b0d5341 804 usage(stderr);
95f1bdee 805
756bfd01
KZ
806 if (all)
807 status |= swapon_all();
63cccae4 808
0b0c231f
KZ
809 for (i = 0; i < numof_labels(); i++)
810 status |= swapon_by_label(get_label(i), priority, discard);
63cccae4 811
0b0c231f
KZ
812 for (i = 0; i < numof_uuids(); i++)
813 status |= swapon_by_uuid(get_uuid(i), priority, discard);
63cccae4
KZ
814
815 while (*argv != NULL)
c2301380 816 status |= do_swapon(*argv++, priority, discard, !CANONIC);
63cccae4 817
0b0c231f 818 free_tables();
6195f9e6 819 mnt_unref_cache(mntcache);
d9f07b10 820
64b58881 821 return status;
6dbe3af9 822}