15 #include <libsmartcols.h>
21 #include "pathnames.h"
25 #include "closestream.h"
27 #include "swapheader.h"
28 #include "swapprober.h"
29 #include "swapon-common.h"
31 #ifdef HAVE_SYS_SWAP_H
32 # include <sys/swap.h>
35 #ifndef SWAP_FLAG_DISCARD
36 # define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */
39 #ifndef SWAP_FLAG_DISCARD_ONCE
40 # define SWAP_FLAG_DISCARD_ONCE 0x20000 /* discard swap area at swapon-time */
43 #ifndef SWAP_FLAG_DISCARD_PAGES
44 # define SWAP_FLAG_DISCARD_PAGES 0x40000 /* discard page-clusters after use */
47 #define SWAP_FLAGS_DISCARD_VALID (SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | \
48 SWAP_FLAG_DISCARD_PAGES)
50 #ifndef SWAP_FLAG_PREFER
51 # define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
54 #ifndef SWAP_FLAG_PRIO_MASK
55 # define SWAP_FLAG_PRIO_MASK 0x7fff
58 #ifndef SWAP_FLAG_PRIO_SHIFT
59 # define SWAP_FLAG_PRIO_SHIFT 0
62 #if !defined(HAVE_SWAPON) && defined(SYS_swapon)
63 # include <sys/syscall.h>
64 # define swapon(path, flags) syscall(SYS_swapon, path, flags)
67 #define MAX_PAGESIZE (64 * 1024)
70 # define UUID_STR_LEN 37
80 const char * const name
; /* header */
81 double whint
; /* width hint (N < 1 is in percent of termwidth) */
82 int flags
; /* SCOLS_FL_* */
95 static const struct colinfo infos
[] = {
96 [COL_PATH
] = { "NAME", 0.20, 0, N_("device file or partition path") },
97 [COL_TYPE
] = { "TYPE", 0.20, SCOLS_FL_TRUNC
, N_("type of the device")},
98 [COL_SIZE
] = { "SIZE", 0.20, SCOLS_FL_RIGHT
, N_("size of the swap area")},
99 [COL_USED
] = { "USED", 0.20, SCOLS_FL_RIGHT
, N_("bytes in use")},
100 [COL_PRIO
] = { "PRIO", 0.20, SCOLS_FL_RIGHT
, N_("swap priority")},
101 [COL_UUID
] = { "UUID", 0.20, 0, N_("swap uuid")},
102 [COL_LABEL
] = { "LABEL", 0.20, 0, N_("swap label")},
106 /* swap area properties */
108 int discard
; /* discard policy */
109 int priority
; /* non-prioritized swap by default */
110 int no_fail
; /* skip device if not exist */
113 /* device description */
115 const char *path
; /* device or file to be turned on */
116 const char *label
; /* swap label */
117 const char *uuid
; /* unique identifier */
118 unsigned int pagesize
;
123 int columns
[ARRAY_SIZE(infos
) * 2]; /* --show columns */
124 int ncolumns
; /* number of columns */
126 struct swap_prop props
; /* global settings for all devices */
129 all
:1, /* turn on all swap devices */
130 bytes
:1, /* display --show in bytes */
131 fix_page_size
:1, /* reinitialize page size */
132 no_heading
:1, /* toggle --show headers */
133 raw
:1, /* toggle --show alignment */
134 show
:1, /* display --show information */
135 verbose
:1; /* be chatty */
138 static int column_name_to_id(const char *name
, size_t namesz
)
144 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++) {
145 const char *cn
= infos
[i
].name
;
147 if (!strncasecmp(name
, cn
, namesz
) && !*(cn
+ namesz
))
150 warnx(_("unknown column: %s"), name
);
154 static inline int get_column_id(const struct swapon_ctl
*ctl
, int num
)
156 assert(num
< ctl
->ncolumns
);
157 assert(ctl
->columns
[num
] < (int) ARRAY_SIZE(infos
));
159 return ctl
->columns
[num
];
162 static inline const struct colinfo
*get_column_info(const struct swapon_ctl
*ctl
, unsigned num
)
164 return &infos
[get_column_id(ctl
, num
)];
167 static void add_scols_line(const struct swapon_ctl
*ctl
, struct libscols_table
*table
, struct libmnt_fs
*fs
)
170 struct libscols_line
*line
;
171 blkid_probe pr
= NULL
;
177 line
= scols_table_new_line(table
, NULL
);
179 err(EXIT_FAILURE
, _("failed to allocate output line"));
181 data
= mnt_fs_get_source(fs
);
182 if (access(data
, R_OK
) == 0)
183 pr
= get_swap_prober(data
);
184 for (i
= 0; i
< ctl
->ncolumns
; i
++) {
188 switch (get_column_id(ctl
, i
)) {
190 xasprintf(&str
, "%s", mnt_fs_get_source(fs
));
193 xasprintf(&str
, "%s", mnt_fs_get_swaptype(fs
));
196 size
= mnt_fs_get_size(fs
);
197 size
*= 1024; /* convert to bytes */
199 xasprintf(&str
, "%jd", size
);
201 str
= size_to_human_string(SIZE_SUFFIX_1LETTER
, size
);
204 size
= mnt_fs_get_usedsize(fs
);
205 size
*= 1024; /* convert to bytes */
207 xasprintf(&str
, "%jd", size
);
209 str
= size_to_human_string(SIZE_SUFFIX_1LETTER
, size
);
212 xasprintf(&str
, "%d", mnt_fs_get_priority(fs
));
215 if (pr
&& !blkid_probe_lookup_value(pr
, "UUID", &data
, NULL
))
216 xasprintf(&str
, "%s", data
);
219 if (pr
&& !blkid_probe_lookup_value(pr
, "LABEL", &data
, NULL
))
220 xasprintf(&str
, "%s", data
);
226 if (str
&& scols_line_refer_data(line
, i
, str
))
227 err(EXIT_FAILURE
, _("failed to add output data"));
230 blkid_free_probe(pr
);
233 static int display_summary(void)
235 struct libmnt_table
*st
= get_swaps();
236 struct libmnt_iter
*itr
;
237 struct libmnt_fs
*fs
;
242 if (mnt_table_is_empty(st
))
245 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
247 err(EXIT_FAILURE
, _("failed to initialize libmount iterator"));
249 /* TRANSLATORS: The tabs make each field a multiple of 8 characters. Keep aligned with each entry below. */
250 printf(_("Filename\t\t\t\tType\t\tSize\t\tUsed\t\tPriority\n"));
252 while (mnt_table_next_fs(st
, itr
, &fs
) == 0) {
253 const char *src
= mnt_fs_get_source(fs
);
254 const char *type
= mnt_fs_get_swaptype(fs
);
255 int srclen
= strlen(src
);
256 int typelen
= strlen(type
);
257 off_t size
= mnt_fs_get_size(fs
);
258 off_t used
= mnt_fs_get_usedsize(fs
);
260 /* TRANSLATORS: Keep each field a multiple of 8 characters and aligned with the header above. */
261 printf("%s%*s%s%s\t%jd%s\t%jd%s\t%d\n",
263 srclen
< 40 ? 40 - srclen
: 1, " ",
265 typelen
< 8 ? "\t" : "",
267 size
< 10000000 ? "\t" : "",
269 used
< 10000000 ? "\t" : "",
270 mnt_fs_get_priority(fs
));
277 static int show_table(struct swapon_ctl
*ctl
)
279 struct libmnt_table
*st
= get_swaps();
280 struct libmnt_iter
*itr
= NULL
;
281 struct libmnt_fs
*fs
;
283 struct libscols_table
*table
= NULL
;
288 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
290 err(EXIT_FAILURE
, _("failed to initialize libmount iterator"));
294 table
= scols_new_table();
296 err(EXIT_FAILURE
, _("failed to allocate output table"));
298 scols_table_enable_raw(table
, ctl
->raw
);
299 scols_table_enable_noheadings(table
, ctl
->no_heading
);
301 for (i
= 0; i
< ctl
->ncolumns
; i
++) {
302 const struct colinfo
*col
= get_column_info(ctl
, i
);
304 if (!scols_table_new_column(table
, col
->name
, col
->whint
, col
->flags
))
305 err(EXIT_FAILURE
, _("failed to allocate output column"));
308 while (mnt_table_next_fs(st
, itr
, &fs
) == 0)
309 add_scols_line(ctl
, table
, fs
);
311 scols_print_table(table
);
312 scols_unref_table(table
);
318 static int swap_reinitialize(struct swap_device
*dev
)
328 warnx(_("%s: reinitializing the swap."), dev
->path
);
330 switch ((pid
=fork())) {
331 case -1: /* fork error */
332 warn(_("fork failed"));
336 if (geteuid() != getuid() && drop_permissions() != 0)
339 cmd
[idx
++] = "mkswap";
342 cmd
[idx
++] = dev
->label
;
346 cmd
[idx
++] = dev
->uuid
;
348 cmd
[idx
++] = dev
->path
;
350 execvp(cmd
[0], (char * const *) cmd
);
353 default: /* parent */
355 ret
= waitpid(pid
, &status
, 0);
356 } while (ret
== -1 && errno
== EINTR
);
359 warn(_("waitpid failed"));
363 /* mkswap returns: 0=suss, >0 error */
364 if (WIFEXITED(status
) && WEXITSTATUS(status
)==0)
368 return -1; /* error */
371 /* Replaces unwanted SWSUSPEND signature with swap signature */
372 static int swap_rewrite_signature(const struct swap_device
*dev
)
378 assert(dev
->pagesize
);
380 fd
= open(dev
->path
, O_WRONLY
);
382 warn(_("cannot open %s"), dev
->path
);
386 if (lseek(fd
, dev
->pagesize
- SWAP_SIGNATURE_SZ
, SEEK_SET
) < 0) {
387 warn(_("%s: lseek failed"), dev
->path
);
391 if (write(fd
, (void *) SWAP_SIGNATURE
,
392 SWAP_SIGNATURE_SZ
) != SWAP_SIGNATURE_SZ
) {
393 warn(_("%s: write signature failed"), dev
->path
);
399 if (close_fd(fd
) != 0) {
400 warn(_("write failed: %s"), dev
->path
);
406 static int swap_detect_signature(const char *buf
, int *sig
)
411 if (memcmp(buf
, SWAP_SIGNATURE
, SWAP_SIGNATURE_SZ
) == 0)
412 *sig
= SIG_SWAPSPACE
;
414 else if (memcmp(buf
, "S1SUSPEND", 9) == 0 ||
415 memcmp(buf
, "S2SUSPEND", 9) == 0 ||
416 memcmp(buf
, "ULSUSPEND", 9) == 0 ||
417 memcmp(buf
, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0 ||
418 memcmp(buf
, "LINHIB0001", 10) == 0)
419 *sig
= SIG_SWSUSPEND
;
426 static char *swap_get_header(int fd
, int *sig
, unsigned int *pagesize
)
438 buf
= xmalloc(MAX_PAGESIZE
);
440 datasz
= read(fd
, buf
, MAX_PAGESIZE
);
441 if (datasz
== (ssize_t
) -1)
444 for (page
= 0x1000; page
<= MAX_PAGESIZE
; page
<<= 1) {
445 /* skip 32k pagesize since this does not seem to
449 /* the smallest swap area is PAGE_SIZE*10, it means
450 * 40k, that's less than MAX_PAGESIZE */
451 if (datasz
< 0 || (size_t) datasz
< (page
- SWAP_SIGNATURE_SZ
))
453 if (swap_detect_signature(buf
+ page
- SWAP_SIGNATURE_SZ
, sig
)) {
466 /* returns real size of swap space */
467 static unsigned long long swap_get_size(const struct swap_device
*dev
,
470 unsigned int last_page
= 0;
471 const unsigned int swap_version
= SWAP_VERSION
;
472 const struct swap_header_v1_2
*s
;
475 assert(dev
->pagesize
> 0);
477 s
= (const struct swap_header_v1_2
*) hdr
;
479 if (s
->version
== swap_version
)
480 last_page
= s
->last_page
;
481 else if (swab32(s
->version
) == swap_version
)
482 last_page
= swab32(s
->last_page
);
484 return ((unsigned long long) last_page
+ 1) * dev
->pagesize
;
487 static void swap_get_info(struct swap_device
*dev
, const char *hdr
)
489 const struct swap_header_v1_2
*s
= (const struct swap_header_v1_2
*) hdr
;
493 if (s
&& *s
->volume_name
)
494 dev
->label
= xstrdup(s
->volume_name
);
497 const unsigned char *u
= s
->uuid
;
498 char str
[UUID_STR_LEN
];
500 snprintf(str
, sizeof(str
),
503 "%02x%02x-%02x%02x%02x%02x%02x%02x",
504 u
[0], u
[1], u
[2], u
[3],
505 u
[4], u
[5], u
[6], u
[7],
506 u
[8], u
[9], u
[10], u
[11], u
[12], u
[13], u
[14], u
[15]);
507 dev
->uuid
= xstrdup(str
);
511 static int swapon_checks(const struct swapon_ctl
*ctl
, struct swap_device
*dev
)
516 unsigned long long devsize
= 0;
523 fd
= open(dev
->path
, O_RDONLY
);
525 warn(_("cannot open %s"), dev
->path
);
529 if (fstat(fd
, &st
) < 0) {
530 warn(_("stat of %s failed"), dev
->path
);
534 permMask
= S_ISBLK(st
.st_mode
) ? 07007 : 07077;
535 if ((st
.st_mode
& permMask
) != 0)
536 warnx(_("%s: insecure permissions %04o, %04o suggested."),
537 dev
->path
, st
.st_mode
& 07777,
540 if (S_ISREG(st
.st_mode
) && st
.st_uid
!= 0)
541 warnx(_("%s: insecure file owner %d, 0 (root) suggested."),
542 dev
->path
, st
.st_uid
);
544 /* test for holes by LBT */
545 if (S_ISREG(st
.st_mode
)) {
546 if (st
.st_blocks
* 512L < st
.st_size
) {
547 warnx(_("%s: skipping - it appears to have holes."),
551 devsize
= st
.st_size
;
554 if (S_ISBLK(st
.st_mode
) && blkdev_get_size(fd
, &devsize
)) {
555 warnx(_("%s: get size failed"), dev
->path
);
559 hdr
= swap_get_header(fd
, &sig
, &dev
->pagesize
);
561 warnx(_("%s: read swap header failed"), dev
->path
);
566 warnx(_("%s: found signature [pagesize=%d, signature=%s]"),
569 sig
== SIG_SWAPSPACE
? "swap" :
570 sig
== SIG_SWSUSPEND
? "suspend" : "unknown");
572 if (sig
== SIG_SWAPSPACE
&& dev
->pagesize
) {
573 unsigned long long swapsize
= swap_get_size(dev
, hdr
);
574 int syspg
= getpagesize();
577 warnx(_("%s: pagesize=%d, swapsize=%llu, devsize=%llu"),
578 dev
->path
, dev
->pagesize
, swapsize
, devsize
);
580 if (swapsize
> devsize
) {
582 warnx(_("%s: last_page 0x%08llx is larger"
583 " than actual size of swapspace"),
584 dev
->path
, swapsize
);
586 } else if (syspg
< 0 || (unsigned int) syspg
!= dev
->pagesize
) {
587 if (ctl
->fix_page_size
) {
590 swap_get_info(dev
, hdr
);
592 warnx(_("%s: swap format pagesize does not match."),
594 rc
= swap_reinitialize(dev
);
598 warnx(_("%s: swap format pagesize does not match. "
599 "(Use --fixpgsz to reinitialize it.)"),
602 } else if (sig
== SIG_SWSUSPEND
) {
603 /* We have to reinitialize swap with old (=useless) software suspend
604 * data. The problem is that if we don't do it, then we get data
605 * corruption the next time an attempt at unsuspending is made.
607 warnx(_("%s: software suspend data detected. "
608 "Rewriting the swap signature."),
610 if (swap_rewrite_signature(dev
) < 0)
624 static int do_swapon(const struct swapon_ctl
*ctl
,
625 const struct swap_prop
*prop
,
629 struct swap_device dev
= { .path
= NULL
};
638 dev
.path
= mnt_resolve_spec(spec
, mntcache
);
640 return cannot_find(spec
);
644 priority
= prop
->priority
;
646 if (swapon_checks(ctl
, &dev
))
649 #ifdef SWAP_FLAG_PREFER
651 if (priority
> SWAP_FLAG_PRIO_MASK
)
652 priority
= SWAP_FLAG_PRIO_MASK
;
654 flags
= SWAP_FLAG_PREFER
655 | ((priority
& SWAP_FLAG_PRIO_MASK
)
656 << SWAP_FLAG_PRIO_SHIFT
);
660 * Validate the discard flags passed and set them
661 * accordingly before calling sys_swapon.
663 if (prop
->discard
&& !(prop
->discard
& ~SWAP_FLAGS_DISCARD_VALID
)) {
665 * If we get here with both discard policy flags set,
666 * we just need to tell the kernel to enable discards
667 * and it will do correctly, just as we expect.
669 if ((prop
->discard
& SWAP_FLAG_DISCARD_ONCE
) &&
670 (prop
->discard
& SWAP_FLAG_DISCARD_PAGES
))
671 flags
|= SWAP_FLAG_DISCARD
;
673 flags
|= prop
->discard
;
677 printf(_("swapon %s\n"), dev
.path
);
679 status
= swapon(dev
.path
, flags
);
681 warn(_("%s: swapon failed"), dev
.path
);
686 static int swapon_by_label(struct swapon_ctl
*ctl
, const char *label
)
688 char *device
= mnt_resolve_tag("LABEL", label
, mntcache
);
689 return device
? do_swapon(ctl
, &ctl
->props
, device
, TRUE
) : cannot_find(label
);
692 static int swapon_by_uuid(struct swapon_ctl
*ctl
, const char *uuid
)
694 char *device
= mnt_resolve_tag("UUID", uuid
, mntcache
);
695 return device
? do_swapon(ctl
, &ctl
->props
, device
, TRUE
) : cannot_find(uuid
);
698 /* -o <options> or fstab */
699 static int parse_options(struct swap_prop
*props
, const char *options
)
707 if (mnt_optstr_get_option(options
, "nofail", NULL
, NULL
) == 0)
710 if (mnt_optstr_get_option(options
, "discard", &arg
, &argsz
) == 0) {
711 props
->discard
|= SWAP_FLAG_DISCARD
;
714 /* only single-time discards are wanted */
715 if (strncmp(arg
, "once", argsz
) == 0)
716 props
->discard
|= SWAP_FLAG_DISCARD_ONCE
;
718 /* do discard for every released swap page */
719 if (strncmp(arg
, "pages", argsz
) == 0)
720 props
->discard
|= SWAP_FLAG_DISCARD_PAGES
;
725 if (mnt_optstr_get_option(options
, "pri", &arg
, &argsz
) == 0 && arg
) {
730 n
= (int) strtol(arg
, &end
, 10);
731 if (errno
== 0 && end
&& end
> arg
)
738 static int swapon_all(struct swapon_ctl
*ctl
, const char *filename
)
740 struct libmnt_table
*tb
= get_fstab(filename
);
741 struct libmnt_iter
*itr
;
742 struct libmnt_fs
*fs
;
746 err(EXIT_FAILURE
, _("failed to parse %s"), mnt_get_fstab_path());
748 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
750 err(EXIT_FAILURE
, _("failed to initialize libmount iterator"));
752 while (mnt_table_find_next_fs(tb
, itr
, match_swap
, NULL
, &fs
) == 0) {
756 struct swap_prop prop
; /* per device setting */
758 if (mnt_fs_get_option(fs
, "noauto", NULL
, NULL
) == 0) {
760 warnx(_("%s: noauto option -- ignored"), mnt_fs_get_source(fs
));
764 /* default setting */
767 /* overwrite default by setting from fstab */
768 opts
= mnt_fs_get_options(fs
);
770 parse_options(&prop
, opts
);
772 /* convert LABEL=, UUID= etc. from fstab to device name */
773 device
= mnt_resolve_spec(mnt_fs_get_source(fs
), mntcache
);
776 status
|= cannot_find(mnt_fs_get_source(fs
));
780 if (is_active_swap(device
)) {
782 warnx(_("%s: already active -- ignored"), device
);
786 if (prop
.no_fail
&& access(device
, R_OK
) != 0) {
788 warnx(_("%s: inaccessible -- ignored"), device
);
793 status
|= do_swapon(ctl
, &prop
, device
, TRUE
);
801 static void __attribute__((__noreturn__
)) usage(void)
806 fputs(USAGE_HEADER
, out
);
807 fprintf(out
, _(" %s [options] [<spec>]\n"), program_invocation_short_name
);
809 fputs(USAGE_SEPARATOR
, out
);
810 fputs(_("Enable devices and files for paging and swapping.\n"), out
);
812 fputs(USAGE_OPTIONS
, out
);
813 fputs(_(" -a, --all enable all swaps from /etc/fstab\n"), out
);
814 fputs(_(" -d, --discard[=<policy>] enable swap discards, if supported by device\n"), out
);
815 fputs(_(" -e, --ifexists silently skip devices that do not exist\n"), out
);
816 fputs(_(" -f, --fixpgsz reinitialize the swap space if necessary\n"), out
);
817 fputs(_(" -o, --options <list> comma-separated list of swap options\n"), out
);
818 fputs(_(" -p, --priority <prio> specify the priority of the swap device\n"), out
);
819 fputs(_(" -s, --summary display summary about used swap devices (DEPRECATED)\n"), out
);
820 fputs(_(" -T, --fstab <path> alternative file to /etc/fstab\n"), out
);
821 fputs(_(" --show[=<columns>] display summary in definable table\n"), out
);
822 fputs(_(" --noheadings don't print table heading (with --show)\n"), out
);
823 fputs(_(" --raw use the raw output format (with --show)\n"), out
);
824 fputs(_(" --bytes display swap size in bytes in --show output\n"), out
);
825 fputs(_(" -v, --verbose verbose mode\n"), out
);
827 fputs(USAGE_SEPARATOR
, out
);
828 fprintf(out
, USAGE_HELP_OPTIONS(26));
830 fputs(_("\nThe <spec> parameter:\n" \
831 " -L <label> synonym for LABEL=<label>\n"
832 " -U <uuid> synonym for UUID=<uuid>\n"
833 " LABEL=<label> specifies device by swap area label\n"
834 " UUID=<uuid> specifies device by swap area UUID\n"
835 " PARTLABEL=<label> specifies device by partition label\n"
836 " PARTUUID=<uuid> specifies device by partition UUID\n"
837 " <device> name of device to be used\n"
838 " <file> name of file to be used\n"), out
);
840 fputs(_("\nAvailable discard policy types (for --discard):\n"
841 " once : only single-time area discards are issued\n"
842 " pages : freed pages are discarded before they are reused\n"
843 "If no policy is selected, both discard types are enabled (default).\n"), out
);
845 fputs(USAGE_COLUMNS
, out
);
846 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++)
847 fprintf(out
, " %-5s %s\n", infos
[i
].name
, _(infos
[i
].help
));
849 fprintf(out
, USAGE_MAN_TAIL("swapon(8)"));
853 int main(int argc
, char *argv
[])
857 char *options
= NULL
, *fstab_filename
= NULL
;
860 BYTES_OPTION
= CHAR_MAX
+ 1,
867 static const struct option long_opts
[] = {
868 { "priority", required_argument
, NULL
, 'p' },
869 { "discard", optional_argument
, NULL
, 'd' },
870 { "ifexists", no_argument
, NULL
, 'e' },
871 { "options", optional_argument
, NULL
, 'o' },
872 { "summary", no_argument
, NULL
, 's' },
873 { "fixpgsz", no_argument
, NULL
, 'f' },
874 { "all", no_argument
, NULL
, 'a' },
875 { "help", no_argument
, NULL
, 'h' },
876 { "verbose", no_argument
, NULL
, 'v' },
877 { "version", no_argument
, NULL
, 'V' },
878 { "show", optional_argument
, NULL
, SHOW_OPTION
},
879 { "output-all", no_argument
, NULL
, OPT_LIST_TYPES
},
880 { "noheadings", no_argument
, NULL
, NOHEADINGS_OPTION
},
881 { "raw", no_argument
, NULL
, RAW_OPTION
},
882 { "bytes", no_argument
, NULL
, BYTES_OPTION
},
883 { "fstab", required_argument
, NULL
, 'T' },
887 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
888 { 'a','o','s', SHOW_OPTION
},
889 { 'a','o', BYTES_OPTION
},
890 { 'a','o', NOHEADINGS_OPTION
},
891 { 'a','o', RAW_OPTION
},
894 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
896 struct swapon_ctl ctl
;
898 setlocale(LC_ALL
, "");
899 bindtextdomain(PACKAGE
, LOCALEDIR
);
901 close_stdout_atexit();
903 memset(&ctl
, 0, sizeof(struct swapon_ctl
));
904 ctl
.props
.priority
= -1;
907 mntcache
= mnt_new_cache();
909 while ((c
= getopt_long(argc
, argv
, "ahd::efo:p:svVL:U:T:",
910 long_opts
, NULL
)) != -1) {
912 err_exclusive_options(c
, long_opts
, excl
, excl_st
);
921 case 'p': /* priority */
922 ctl
.props
.priority
= strtos16_or_err(optarg
,
923 _("failed to parse priority"));
932 fstab_filename
= optarg
;
935 ctl
.props
.discard
|= SWAP_FLAG_DISCARD
;
940 if (strcmp(optarg
, "once") == 0)
941 ctl
.props
.discard
|= SWAP_FLAG_DISCARD_ONCE
;
942 else if (strcmp(optarg
, "pages") == 0)
943 ctl
.props
.discard
|= SWAP_FLAG_DISCARD_PAGES
;
945 errx(EXIT_FAILURE
, _("unsupported discard policy: %s"), optarg
);
948 case 'e': /* ifexists */
949 ctl
.props
.no_fail
= 1;
952 ctl
.fix_page_size
= 1;
954 case 's': /* status report */
955 status
= display_summary();
957 case 'v': /* be chatty */
962 ctl
.ncolumns
= string_to_idarray(optarg
,
964 ARRAY_SIZE(ctl
.columns
),
966 if (ctl
.ncolumns
< 0)
972 for (ctl
.ncolumns
= 0; (size_t)ctl
.ncolumns
< ARRAY_SIZE(infos
); ctl
.ncolumns
++)
973 ctl
.columns
[ctl
.ncolumns
] = ctl
.ncolumns
;
975 case NOHEADINGS_OPTION
:
989 case 'V': /* version */
990 print_version(EXIT_SUCCESS
);
992 errtryhelp(EXIT_FAILURE
);
997 if (ctl
.show
|| (!ctl
.all
&& !numof_labels() && !numof_uuids() && *argv
== NULL
)) {
999 /* default columns */
1000 ctl
.columns
[ctl
.ncolumns
++] = COL_PATH
;
1001 ctl
.columns
[ctl
.ncolumns
++] = COL_TYPE
;
1002 ctl
.columns
[ctl
.ncolumns
++] = COL_SIZE
;
1003 ctl
.columns
[ctl
.ncolumns
++] = COL_USED
;
1004 ctl
.columns
[ctl
.ncolumns
++] = COL_PRIO
;
1006 status
= show_table(&ctl
);
1010 if (ctl
.props
.no_fail
&& !ctl
.all
) {
1011 warnx(_("bad usage"));
1012 errtryhelp(EXIT_FAILURE
);
1016 status
|= swapon_all(&ctl
, fstab_filename
);
1019 parse_options(&ctl
.props
, options
);
1021 for (i
= 0; i
< numof_labels(); i
++)
1022 status
|= swapon_by_label(&ctl
, get_label(i
));
1024 for (i
= 0; i
< numof_uuids(); i
++)
1025 status
|= swapon_by_uuid(&ctl
, get_uuid(i
));
1027 while (*argv
!= NULL
)
1028 status
|= do_swapon(&ctl
, &ctl
.props
, *argv
++, FALSE
);
1031 mnt_unref_cache(mntcache
);