]>
Commit | Line | Data |
---|---|---|
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 | |
248a7f70 | 15 | #include <libsmartcols.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" |
18b3e549 | 23 | #include "strutils.h" |
e07fdac4 | 24 | #include "optutils.h" |
efb8854f | 25 | #include "closestream.h" |
167eaed7 | 26 | |
d335c9bd | 27 | #include "swapheader.h" |
18b3e549 | 28 | #include "swapprober.h" |
0b0c231f KZ |
29 | #include "swapon-common.h" |
30 | ||
ffa63a3d MF |
31 | #ifdef HAVE_SYS_SWAP_H |
32 | # include <sys/swap.h> | |
33 | #endif | |
34 | ||
c2301380 | 35 | #ifndef SWAP_FLAG_DISCARD |
d6387c98 | 36 | # define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */ |
c2301380 HD |
37 | #endif |
38 | ||
d6387c98 RA |
39 | #ifndef SWAP_FLAG_DISCARD_ONCE |
40 | # define SWAP_FLAG_DISCARD_ONCE 0x20000 /* discard swap area at swapon-time */ | |
41 | #endif | |
42 | ||
43 | #ifndef SWAP_FLAG_DISCARD_PAGES | |
44 | # define SWAP_FLAG_DISCARD_PAGES 0x40000 /* discard page-clusters after use */ | |
45 | #endif | |
46 | ||
47 | #define SWAP_FLAGS_DISCARD_VALID (SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | \ | |
48 | SWAP_FLAG_DISCARD_PAGES) | |
49 | ||
9514a612 KZ |
50 | #ifndef SWAP_FLAG_PREFER |
51 | # define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ | |
52 | #endif | |
53 | ||
54 | #ifndef SWAP_FLAG_PRIO_MASK | |
55 | # define SWAP_FLAG_PRIO_MASK 0x7fff | |
56 | #endif | |
57 | ||
58 | #ifndef SWAP_FLAG_PRIO_SHIFT | |
59 | # define SWAP_FLAG_PRIO_SHIFT 0 | |
60 | #endif | |
61 | ||
cf9b16f1 | 62 | #if !defined(HAVE_SWAPON) && defined(SYS_swapon) |
ffa63a3d MF |
63 | # include <sys/syscall.h> |
64 | # define swapon(path, flags) syscall(SYS_swapon, path, flags) | |
ffa63a3d MF |
65 | #endif |
66 | ||
3399a218 MK |
67 | #define MAX_PAGESIZE (64 * 1024) |
68 | ||
b443c177 | 69 | #ifndef UUID_STR_LEN |
9f20d800 | 70 | # define UUID_STR_LEN 37 |
b443c177 PP |
71 | #endif |
72 | ||
e8be80dd KZ |
73 | enum { |
74 | SIG_SWAPSPACE = 1, | |
75 | SIG_SWSUSPEND | |
76 | }; | |
77 | ||
e076b552 SK |
78 | /* column names */ |
79 | struct colinfo { | |
80 | const char *name; /* header */ | |
81 | double whint; /* width hint (N < 1 is in percent of termwidth) */ | |
248a7f70 | 82 | int flags; /* SCOLS_FL_* */ |
e076b552 SK |
83 | const char *help; |
84 | }; | |
248a7f70 | 85 | |
5db57cfc SK |
86 | enum { |
87 | COL_PATH, | |
88 | COL_TYPE, | |
89 | COL_SIZE, | |
90 | COL_USED, | |
91 | COL_PRIO, | |
92 | COL_UUID, | |
93 | COL_LABEL | |
94 | }; | |
2ba641e5 | 95 | static struct colinfo infos[] = { |
e076b552 | 96 | [COL_PATH] = { "NAME", 0.20, 0, N_("device file or partition path") }, |
248a7f70 OO |
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")}, | |
5db57cfc SK |
101 | [COL_UUID] = { "UUID", 0.20, 0, N_("swap uuid")}, |
102 | [COL_LABEL] = { "LABEL", 0.20, 0, N_("swap label")}, | |
e076b552 | 103 | }; |
a560a348 | 104 | |
6c44094a KZ |
105 | |
106 | /* swap area properties */ | |
107 | struct swap_prop { | |
108 | int discard; /* discard policy */ | |
109 | int priority; /* non-prioritized swap by default */ | |
110 | int no_fail; /* skip device if not exist */ | |
111 | }; | |
112 | ||
113 | /* device description */ | |
114 | struct swap_device { | |
115 | const char *path; /* device or file to be turned on */ | |
9eeba70e SK |
116 | const char *label; /* swap label */ |
117 | const char *uuid; /* unique identifier */ | |
6c44094a KZ |
118 | unsigned int pagesize; |
119 | }; | |
120 | ||
121 | /* control struct */ | |
122 | struct swapon_ctl { | |
9eeba70e | 123 | int columns[ARRAY_SIZE(infos) * 2]; /* --show columns */ |
6c44094a KZ |
124 | int ncolumns; /* number of columns */ |
125 | ||
126 | struct swap_prop props; /* global settings for all devices */ | |
127 | ||
9eeba70e SK |
128 | unsigned int |
129 | all:1, /* turn on all swap devices */ | |
130 | bytes:1, /* display --show in bytes */ | |
131 | fix_page_size:1, /* reinitialize page size */ | |
9eeba70e SK |
132 | no_heading:1, /* toggle --show headers */ |
133 | raw:1, /* toggle --show alignment */ | |
134 | show:1, /* display --show information */ | |
135 | verbose:1; /* be chatty */ | |
136 | }; | |
e076b552 SK |
137 | |
138 | static int column_name_to_id(const char *name, size_t namesz) | |
139 | { | |
140 | size_t i; | |
141 | ||
142 | assert(name); | |
143 | ||
a560a348 | 144 | for (i = 0; i < ARRAY_SIZE(infos); i++) { |
e076b552 SK |
145 | const char *cn = infos[i].name; |
146 | ||
147 | if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) | |
148 | return i; | |
149 | } | |
150 | warnx(_("unknown column: %s"), name); | |
151 | return -1; | |
152 | } | |
153 | ||
9eeba70e | 154 | static inline int get_column_id(const struct swapon_ctl *ctl, int num) |
e076b552 | 155 | { |
9eeba70e SK |
156 | assert(num < ctl->ncolumns); |
157 | assert(ctl->columns[num] < (int) ARRAY_SIZE(infos)); | |
e076b552 | 158 | |
9eeba70e | 159 | return ctl->columns[num]; |
e076b552 SK |
160 | } |
161 | ||
9eeba70e | 162 | static inline struct colinfo *get_column_info(const struct swapon_ctl *ctl, unsigned num) |
e076b552 | 163 | { |
9eeba70e | 164 | return &infos[get_column_id(ctl, num)]; |
e076b552 SK |
165 | } |
166 | ||
9eeba70e | 167 | static void add_scols_line(const struct swapon_ctl *ctl, struct libscols_table *table, struct libmnt_fs *fs) |
e076b552 SK |
168 | { |
169 | int i; | |
248a7f70 | 170 | struct libscols_line *line; |
5db57cfc SK |
171 | blkid_probe pr = NULL; |
172 | const char *data; | |
e076b552 | 173 | |
248a7f70 | 174 | assert(table); |
e076b552 SK |
175 | assert(fs); |
176 | ||
248a7f70 | 177 | line = scols_table_new_line(table, NULL); |
e5166348 | 178 | if (!line) |
780ce22c KZ |
179 | err(EXIT_FAILURE, _("failed to allocate output line")); |
180 | ||
5db57cfc SK |
181 | data = mnt_fs_get_source(fs); |
182 | if (access(data, R_OK) == 0) | |
183 | pr = get_swap_prober(data); | |
9eeba70e | 184 | for (i = 0; i < ctl->ncolumns; i++) { |
e076b552 | 185 | char *str = NULL; |
7ae8b469 | 186 | off_t size; |
e076b552 | 187 | |
9eeba70e | 188 | switch (get_column_id(ctl, i)) { |
e076b552 | 189 | case COL_PATH: |
a0e35e30 | 190 | xasprintf(&str, "%s", mnt_fs_get_source(fs)); |
e076b552 SK |
191 | break; |
192 | case COL_TYPE: | |
a0e35e30 | 193 | xasprintf(&str, "%s", mnt_fs_get_swaptype(fs)); |
e076b552 SK |
194 | break; |
195 | case COL_SIZE: | |
7ae8b469 SK |
196 | size = mnt_fs_get_size(fs); |
197 | size *= 1024; /* convert to bytes */ | |
9eeba70e | 198 | if (ctl->bytes) |
a0e35e30 | 199 | xasprintf(&str, "%jd", size); |
7ae8b469 SK |
200 | else |
201 | str = size_to_human_string(SIZE_SUFFIX_1LETTER, size); | |
e076b552 SK |
202 | break; |
203 | case COL_USED: | |
7ae8b469 SK |
204 | size = mnt_fs_get_usedsize(fs); |
205 | size *= 1024; /* convert to bytes */ | |
9eeba70e | 206 | if (ctl->bytes) |
a0e35e30 | 207 | xasprintf(&str, "%jd", size); |
7ae8b469 SK |
208 | else |
209 | str = size_to_human_string(SIZE_SUFFIX_1LETTER, size); | |
e076b552 SK |
210 | break; |
211 | case COL_PRIO: | |
a0e35e30 | 212 | xasprintf(&str, "%d", mnt_fs_get_priority(fs)); |
e076b552 | 213 | break; |
5db57cfc SK |
214 | case COL_UUID: |
215 | if (pr && !blkid_probe_lookup_value(pr, "UUID", &data, NULL)) | |
216 | xasprintf(&str, "%s", data); | |
5db57cfc SK |
217 | break; |
218 | case COL_LABEL: | |
219 | if (pr && !blkid_probe_lookup_value(pr, "LABEL", &data, NULL)) | |
220 | xasprintf(&str, "%s", data); | |
5db57cfc | 221 | break; |
e076b552 SK |
222 | default: |
223 | break; | |
224 | } | |
225 | ||
780ce22c KZ |
226 | if (str && scols_line_refer_data(line, i, str)) |
227 | err(EXIT_FAILURE, _("failed to add output data")); | |
e076b552 | 228 | } |
5db57cfc SK |
229 | if (pr) |
230 | blkid_free_probe(pr); | |
e076b552 SK |
231 | return; |
232 | } | |
233 | ||
d335c9bd | 234 | static int display_summary(void) |
fd6b7a7f | 235 | { |
5072b90a | 236 | struct libmnt_table *st = get_swaps(); |
64b58881 KZ |
237 | struct libmnt_iter *itr; |
238 | struct libmnt_fs *fs; | |
fd6b7a7f | 239 | |
64b58881 | 240 | if (!st) |
57a60bf0 | 241 | return -1; |
e8f26419 | 242 | |
a2f17bb2 KZ |
243 | if (mnt_table_is_empty(st)) |
244 | return 0; | |
245 | ||
64b58881 KZ |
246 | itr = mnt_new_iter(MNT_ITER_FORWARD); |
247 | if (!itr) | |
248 | err(EXIT_FAILURE, _("failed to initialize libmount iterator")); | |
57a60bf0 | 249 | |
a2f17bb2 | 250 | printf(_("%s\t\t\t\tType\t\tSize\tUsed\tPriority\n"), _("Filename")); |
64b58881 KZ |
251 | |
252 | while (mnt_table_next_fs(st, itr, &fs) == 0) { | |
74712441 | 253 | printf("%-39s\t%-8s\t%jd\t%jd\t%d\n", |
64b58881 KZ |
254 | mnt_fs_get_source(fs), |
255 | mnt_fs_get_swaptype(fs), | |
256 | mnt_fs_get_size(fs), | |
257 | mnt_fs_get_usedsize(fs), | |
258 | mnt_fs_get_priority(fs)); | |
57a60bf0 | 259 | } |
fd6b7a7f | 260 | |
64b58881 KZ |
261 | mnt_free_iter(itr); |
262 | return 0; | |
fd6b7a7f KZ |
263 | } |
264 | ||
9eeba70e | 265 | static int show_table(struct swapon_ctl *ctl) |
e076b552 SK |
266 | { |
267 | struct libmnt_table *st = get_swaps(); | |
880f09c8 | 268 | struct libmnt_iter *itr = NULL; |
e076b552 | 269 | struct libmnt_fs *fs; |
e5166348 | 270 | int i; |
248a7f70 | 271 | struct libscols_table *table = NULL; |
e076b552 SK |
272 | |
273 | if (!st) | |
274 | return -1; | |
275 | ||
276 | itr = mnt_new_iter(MNT_ITER_FORWARD); | |
277 | if (!itr) | |
278 | err(EXIT_FAILURE, _("failed to initialize libmount iterator")); | |
279 | ||
710ed55d KZ |
280 | scols_init_debug(0); |
281 | ||
0925a9dd | 282 | table = scols_new_table(); |
e5166348 | 283 | if (!table) |
780ce22c | 284 | err(EXIT_FAILURE, _("failed to allocate output table")); |
e5166348 | 285 | |
9eeba70e SK |
286 | scols_table_enable_raw(table, ctl->raw); |
287 | scols_table_enable_noheadings(table, ctl->no_heading); | |
e076b552 | 288 | |
9eeba70e SK |
289 | for (i = 0; i < ctl->ncolumns; i++) { |
290 | struct colinfo *col = get_column_info(ctl, i); | |
e076b552 | 291 | |
e5166348 | 292 | if (!scols_table_new_column(table, col->name, col->whint, col->flags)) |
780ce22c | 293 | err(EXIT_FAILURE, _("failed to allocate output column")); |
e076b552 SK |
294 | } |
295 | ||
296 | while (mnt_table_next_fs(st, itr, &fs) == 0) | |
9eeba70e | 297 | add_scols_line(ctl, table, fs); |
e076b552 | 298 | |
248a7f70 | 299 | scols_print_table(table); |
248a7f70 | 300 | scols_unref_table(table); |
e5166348 KZ |
301 | mnt_free_iter(itr); |
302 | return 0; | |
e076b552 SK |
303 | } |
304 | ||
6274b987 | 305 | /* calls mkswap */ |
6c44094a | 306 | static int swap_reinitialize(struct swap_device *dev) |
b5b2c388 | 307 | { |
6274b987 KC |
308 | pid_t pid; |
309 | int status, ret; | |
2dd3ba2c | 310 | char const *cmd[7]; |
6274b987 KC |
311 | int idx=0; |
312 | ||
6c44094a KZ |
313 | assert(dev); |
314 | assert(dev->path); | |
315 | ||
316 | warnx(_("%s: reinitializing the swap."), dev->path); | |
0d761944 | 317 | |
a125123f | 318 | switch ((pid=fork())) { |
6274b987 | 319 | case -1: /* fork error */ |
d51d05d3 | 320 | warn(_("fork failed")); |
6274b987 KC |
321 | return -1; |
322 | ||
323 | case 0: /* child */ | |
eac478dc KZ |
324 | if (geteuid() != getuid()) { |
325 | /* in case someone uses swapon as setuid binary */ | |
326 | if (setgid(getgid()) < 0) | |
327 | exit(EXIT_FAILURE); | |
328 | if (setuid(getuid()) < 0) | |
329 | exit(EXIT_FAILURE); | |
330 | } | |
331 | ||
f1bc5996 | 332 | cmd[idx++] = "mkswap"; |
6c44094a | 333 | if (dev->label) { |
6274b987 | 334 | cmd[idx++] = "-L"; |
6c44094a | 335 | cmd[idx++] = dev->label; |
6274b987 | 336 | } |
6c44094a | 337 | if (dev->uuid) { |
6274b987 | 338 | cmd[idx++] = "-U"; |
6c44094a | 339 | cmd[idx++] = dev->uuid; |
6274b987 | 340 | } |
6c44094a | 341 | cmd[idx++] = dev->path; |
6274b987 | 342 | cmd[idx++] = NULL; |
2dd3ba2c | 343 | execvp(cmd[0], (char * const *) cmd); |
fd777151 | 344 | errexec(cmd[0]); |
6274b987 KC |
345 | |
346 | default: /* parent */ | |
347 | do { | |
048811c9 KZ |
348 | ret = waitpid(pid, &status, 0); |
349 | } while (ret == -1 && errno == EINTR); | |
350 | ||
351 | if (ret < 0) { | |
352 | warn(_("waitpid failed")); | |
353 | return -1; | |
354 | } | |
6274b987 | 355 | |
fd777151 | 356 | /* mkswap returns: 0=suss, >0 error */ |
6274b987 KC |
357 | if (WIFEXITED(status) && WEXITSTATUS(status)==0) |
358 | return 0; /* ok */ | |
f8ff4ebb | 359 | break; |
6274b987 KC |
360 | } |
361 | return -1; /* error */ | |
362 | } | |
363 | ||
6c44094a KZ |
364 | /* Replaces unwanted SWSUSPEND signature with swap signature */ |
365 | static int swap_rewrite_signature(const struct swap_device *dev) | |
617d8a3b KZ |
366 | { |
367 | int fd, rc = -1; | |
368 | ||
6c44094a KZ |
369 | assert(dev); |
370 | assert(dev->path); | |
371 | assert(dev->pagesize); | |
372 | ||
373 | fd = open(dev->path, O_WRONLY); | |
617d8a3b | 374 | if (fd == -1) { |
6c44094a | 375 | warn(_("cannot open %s"), dev->path); |
617d8a3b KZ |
376 | return -1; |
377 | } | |
378 | ||
6c44094a KZ |
379 | if (lseek(fd, dev->pagesize - SWAP_SIGNATURE_SZ, SEEK_SET) < 0) { |
380 | warn(_("%s: lseek failed"), dev->path); | |
617d8a3b | 381 | goto err; |
5dd53f43 | 382 | } |
617d8a3b KZ |
383 | |
384 | if (write(fd, (void *) SWAP_SIGNATURE, | |
5dd53f43 | 385 | SWAP_SIGNATURE_SZ) != SWAP_SIGNATURE_SZ) { |
6c44094a | 386 | warn(_("%s: write signature failed"), dev->path); |
617d8a3b | 387 | goto err; |
5dd53f43 | 388 | } |
617d8a3b KZ |
389 | |
390 | rc = 0; | |
391 | err: | |
14699715 | 392 | if (close_fd(fd) != 0) { |
6c44094a | 393 | warn(_("write failed: %s"), dev->path); |
14699715 SK |
394 | rc = -1; |
395 | } | |
617d8a3b KZ |
396 | return rc; |
397 | } | |
398 | ||
d335c9bd | 399 | static int swap_detect_signature(const char *buf, int *sig) |
3399a218 | 400 | { |
6c44094a KZ |
401 | assert(buf); |
402 | assert(sig); | |
403 | ||
eb397d19 | 404 | if (memcmp(buf, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ) == 0) |
e8be80dd KZ |
405 | *sig = SIG_SWAPSPACE; |
406 | ||
407 | else if (memcmp(buf, "S1SUSPEND", 9) == 0 || | |
408 | memcmp(buf, "S2SUSPEND", 9) == 0 || | |
409 | memcmp(buf, "ULSUSPEND", 9) == 0 || | |
5a16af58 KZ |
410 | memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0 || |
411 | memcmp(buf, "LINHIB0001", 10) == 0) | |
e8be80dd KZ |
412 | *sig = SIG_SWSUSPEND; |
413 | else | |
414 | return 0; | |
3399a218 | 415 | |
e8be80dd | 416 | return 1; |
3399a218 MK |
417 | } |
418 | ||
6c44094a | 419 | static char *swap_get_header(int fd, int *sig, unsigned int *pagesize) |
3399a218 | 420 | { |
3399a218 | 421 | char *buf; |
e8be80dd KZ |
422 | ssize_t datasz; |
423 | unsigned int page; | |
3399a218 | 424 | |
6c44094a KZ |
425 | assert(sig); |
426 | assert(pagesize); | |
427 | ||
428 | *pagesize = 0; | |
e8be80dd | 429 | *sig = 0; |
3399a218 | 430 | |
bfbb12d2 | 431 | buf = xmalloc(MAX_PAGESIZE); |
3399a218 MK |
432 | |
433 | datasz = read(fd, buf, MAX_PAGESIZE); | |
e8be80dd KZ |
434 | if (datasz == (ssize_t) -1) |
435 | goto err; | |
3399a218 MK |
436 | |
437 | for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) { | |
438 | /* skip 32k pagesize since this does not seem to | |
439 | * be supported */ | |
440 | if (page == 0x8000) | |
441 | continue; | |
442 | /* the smallest swap area is PAGE_SIZE*10, it means | |
443 | * 40k, that's less than MAX_PAGESIZE */ | |
24f010e8 | 444 | if (datasz < 0 || (size_t) datasz < (page - SWAP_SIGNATURE_SZ)) |
3399a218 | 445 | break; |
617d8a3b | 446 | if (swap_detect_signature(buf + page - SWAP_SIGNATURE_SZ, sig)) { |
6c44094a | 447 | *pagesize = page; |
3399a218 MK |
448 | break; |
449 | } | |
450 | } | |
451 | ||
6c44094a | 452 | if (*pagesize) |
e8be80dd | 453 | return buf; |
3399a218 | 454 | err: |
e8be80dd KZ |
455 | free(buf); |
456 | return NULL; | |
457 | } | |
458 | ||
459 | /* returns real size of swap space */ | |
6c44094a KZ |
460 | static unsigned long long swap_get_size(const struct swap_device *dev, |
461 | const char *hdr) | |
e8be80dd KZ |
462 | { |
463 | unsigned int last_page = 0; | |
8a101b14 | 464 | const unsigned int swap_version = SWAP_VERSION; |
58bc4932 | 465 | const struct swap_header_v1_2 *s; |
e8be80dd | 466 | |
6c44094a KZ |
467 | assert(dev); |
468 | assert(dev->pagesize > 0); | |
469 | ||
58bc4932 | 470 | s = (const struct swap_header_v1_2 *) hdr; |
6c44094a KZ |
471 | |
472 | if (s->version == swap_version) | |
e8be80dd | 473 | last_page = s->last_page; |
6c44094a | 474 | else if (swab32(s->version) == swap_version) |
e8be80dd | 475 | last_page = swab32(s->last_page); |
6c44094a KZ |
476 | |
477 | return ((unsigned long long) last_page + 1) * dev->pagesize; | |
3399a218 MK |
478 | } |
479 | ||
6c44094a | 480 | static void swap_get_info(struct swap_device *dev, const char *hdr) |
b5b2c388 | 481 | { |
58bc4932 | 482 | const struct swap_header_v1_2 *s = (const struct swap_header_v1_2 *) hdr; |
b5b2c388 | 483 | |
6c44094a KZ |
484 | assert(dev); |
485 | ||
a125123f | 486 | if (s && *s->volume_name) |
6c44094a | 487 | dev->label = xstrdup(s->volume_name); |
b5b2c388 | 488 | |
a125123f | 489 | if (s && *s->uuid) { |
b5b2c388 | 490 | const unsigned char *u = s->uuid; |
b443c177 | 491 | char str[UUID_STR_LEN]; |
b5b2c388 KZ |
492 | |
493 | snprintf(str, sizeof(str), | |
494 | "%02x%02x%02x%02x-" | |
495 | "%02x%02x-%02x%02x-" | |
496 | "%02x%02x-%02x%02x%02x%02x%02x%02x", | |
497 | u[0], u[1], u[2], u[3], | |
498 | u[4], u[5], u[6], u[7], | |
499 | u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]); | |
6c44094a | 500 | dev->uuid = xstrdup(str); |
b5b2c388 KZ |
501 | } |
502 | } | |
503 | ||
6c44094a | 504 | static int swapon_checks(const struct swapon_ctl *ctl, struct swap_device *dev) |
05c79b78 | 505 | { |
63cccae4 | 506 | struct stat st; |
1b504263 | 507 | int fd, sig; |
05c79b78 | 508 | char *hdr = NULL; |
e8be80dd | 509 | unsigned long long devsize = 0; |
cd04b26b | 510 | int permMask; |
63cccae4 | 511 | |
6c44094a KZ |
512 | assert(ctl); |
513 | assert(dev); | |
514 | assert(dev->path); | |
515 | ||
516 | fd = open(dev->path, O_RDONLY); | |
8df370d3 | 517 | if (fd == -1) { |
6c44094a | 518 | warn(_("cannot open %s"), dev->path); |
8df370d3 SK |
519 | goto err; |
520 | } | |
521 | ||
522 | if (fstat(fd, &st) < 0) { | |
6c44094a | 523 | warn(_("stat of %s failed"), dev->path); |
05c79b78 | 524 | goto err; |
63cccae4 KZ |
525 | } |
526 | ||
cd04b26b KZ |
527 | permMask = S_ISBLK(st.st_mode) ? 07007 : 07077; |
528 | if ((st.st_mode & permMask) != 0) | |
529 | warnx(_("%s: insecure permissions %04o, %04o suggested."), | |
6c44094a | 530 | dev->path, st.st_mode & 07777, |
88530f9f | 531 | ~permMask & 0666); |
306c1df2 | 532 | |
cd04b26b KZ |
533 | if (S_ISREG(st.st_mode) && st.st_uid != 0) |
534 | warnx(_("%s: insecure file owner %d, 0 (root) suggested."), | |
6c44094a | 535 | dev->path, st.st_uid); |
88530f9f KZ |
536 | |
537 | /* test for holes by LBT */ | |
538 | if (S_ISREG(st.st_mode)) { | |
539 | if (st.st_blocks * 512 < st.st_size) { | |
d51d05d3 | 540 | warnx(_("%s: skipping - it appears to have holes."), |
6c44094a | 541 | dev->path); |
05c79b78 | 542 | goto err; |
88530f9f | 543 | } |
e8be80dd KZ |
544 | devsize = st.st_size; |
545 | } | |
546 | ||
05c79b78 | 547 | if (S_ISBLK(st.st_mode) && blkdev_get_size(fd, &devsize)) { |
6c44094a | 548 | warnx(_("%s: get size failed"), dev->path); |
05c79b78 | 549 | goto err; |
e8be80dd KZ |
550 | } |
551 | ||
6c44094a | 552 | hdr = swap_get_header(fd, &sig, &dev->pagesize); |
e8be80dd | 553 | if (!hdr) { |
6c44094a | 554 | warnx(_("%s: read swap header failed"), dev->path); |
05c79b78 | 555 | goto err; |
88530f9f KZ |
556 | } |
557 | ||
6c44094a KZ |
558 | if (ctl->verbose) |
559 | warnx(_("%s: found signature [pagesize=%d, signature=%s]"), | |
560 | dev->path, | |
561 | dev->pagesize, | |
562 | sig == SIG_SWAPSPACE ? "swap" : | |
563 | sig == SIG_SWSUSPEND ? "suspend" : "unknown"); | |
564 | ||
565 | if (sig == SIG_SWAPSPACE && dev->pagesize) { | |
566 | unsigned long long swapsize = swap_get_size(dev, hdr); | |
24f010e8 KZ |
567 | int syspg = getpagesize(); |
568 | ||
9eeba70e | 569 | if (ctl->verbose) |
e6b0611b | 570 | warnx(_("%s: pagesize=%d, swapsize=%llu, devsize=%llu"), |
6c44094a | 571 | dev->path, dev->pagesize, swapsize, devsize); |
e8be80dd KZ |
572 | |
573 | if (swapsize > devsize) { | |
9eeba70e | 574 | if (ctl->verbose) |
d51d05d3 KZ |
575 | warnx(_("%s: last_page 0x%08llx is larger" |
576 | " than actual size of swapspace"), | |
6c44094a KZ |
577 | dev->path, swapsize); |
578 | ||
579 | } else if (syspg < 0 || (unsigned int) syspg != dev->pagesize) { | |
9eeba70e | 580 | if (ctl->fix_page_size) { |
b5b2c388 KZ |
581 | int rc; |
582 | ||
6c44094a | 583 | swap_get_info(dev, hdr); |
b5b2c388 | 584 | |
93bfcc94 | 585 | warnx(_("%s: swap format pagesize does not match."), |
6c44094a KZ |
586 | dev->path); |
587 | rc = swap_reinitialize(dev); | |
b5b2c388 | 588 | if (rc < 0) |
0d761944 KZ |
589 | goto err; |
590 | } else | |
93bfcc94 KZ |
591 | warnx(_("%s: swap format pagesize does not match. " |
592 | "(Use --fixpgsz to reinitialize it.)"), | |
6c44094a | 593 | dev->path); |
e8be80dd KZ |
594 | } |
595 | } else if (sig == SIG_SWSUSPEND) { | |
596 | /* We have to reinitialize swap with old (=useless) software suspend | |
597 | * data. The problem is that if we don't do it, then we get data | |
598 | * corruption the next time an attempt at unsuspending is made. | |
599 | */ | |
d51d05d3 | 600 | warnx(_("%s: software suspend data detected. " |
617d8a3b | 601 | "Rewriting the swap signature."), |
6c44094a KZ |
602 | dev->path); |
603 | if (swap_rewrite_signature(dev) < 0) | |
05c79b78 | 604 | goto err; |
6274b987 KC |
605 | } |
606 | ||
05c79b78 KZ |
607 | free(hdr); |
608 | close(fd); | |
609 | return 0; | |
05c79b78 KZ |
610 | err: |
611 | if (fd != -1) | |
612 | close(fd); | |
613 | free(hdr); | |
614 | return -1; | |
615 | } | |
63cccae4 | 616 | |
6c44094a KZ |
617 | static int do_swapon(const struct swapon_ctl *ctl, |
618 | const struct swap_prop *prop, | |
619 | const char *spec, | |
620 | int canonic) | |
d335c9bd | 621 | { |
6c44094a | 622 | struct swap_device dev = { .path = NULL }; |
05c79b78 | 623 | int status; |
05c79b78 | 624 | int flags = 0; |
6c44094a | 625 | int priority; |
63cccae4 | 626 | |
6c44094a KZ |
627 | assert(ctl); |
628 | assert(prop); | |
05c79b78 | 629 | |
a125123f | 630 | if (!canonic) { |
6c44094a KZ |
631 | dev.path = mnt_resolve_spec(spec, mntcache); |
632 | if (!dev.path) | |
a125123f | 633 | return cannot_find(spec); |
2dd3ba2c | 634 | } else |
6c44094a | 635 | dev.path = spec; |
ffa63a3d | 636 | |
6c44094a KZ |
637 | priority = prop->priority; |
638 | ||
639 | if (swapon_checks(ctl, &dev)) | |
05c79b78 KZ |
640 | return -1; |
641 | ||
642 | #ifdef SWAP_FLAG_PREFER | |
6c44094a KZ |
643 | if (priority >= 0) { |
644 | if (priority > SWAP_FLAG_PRIO_MASK) | |
645 | priority = SWAP_FLAG_PRIO_MASK; | |
646 | ||
05c79b78 | 647 | flags = SWAP_FLAG_PREFER |
6c44094a | 648 | | ((priority & SWAP_FLAG_PRIO_MASK) |
05c79b78 KZ |
649 | << SWAP_FLAG_PRIO_SHIFT); |
650 | } | |
651 | #endif | |
d6387c98 RA |
652 | /* |
653 | * Validate the discard flags passed and set them | |
654 | * accordingly before calling sys_swapon. | |
655 | */ | |
6c44094a | 656 | if (prop->discard && !(prop->discard & ~SWAP_FLAGS_DISCARD_VALID)) { |
d6387c98 RA |
657 | /* |
658 | * If we get here with both discard policy flags set, | |
659 | * we just need to tell the kernel to enable discards | |
660 | * and it will do correctly, just as we expect. | |
661 | */ | |
6c44094a KZ |
662 | if ((prop->discard & SWAP_FLAG_DISCARD_ONCE) && |
663 | (prop->discard & SWAP_FLAG_DISCARD_PAGES)) | |
d6387c98 RA |
664 | flags |= SWAP_FLAG_DISCARD; |
665 | else | |
6c44094a | 666 | flags |= prop->discard; |
d6387c98 | 667 | } |
c2301380 | 668 | |
6c44094a KZ |
669 | if (ctl->verbose) |
670 | printf(_("swapon %s\n"), dev.path); | |
671 | ||
672 | status = swapon(dev.path, flags); | |
d51d05d3 | 673 | if (status < 0) |
6c44094a | 674 | warn(_("%s: swapon failed"), dev.path); |
63cccae4 KZ |
675 | |
676 | return status; | |
677 | } | |
678 | ||
a125123f | 679 | static int swapon_by_label(struct swapon_ctl *ctl, const char *label) |
d335c9bd | 680 | { |
a125123f | 681 | char *device = mnt_resolve_tag("LABEL", label, mntcache); |
6c44094a | 682 | return device ? do_swapon(ctl, &ctl->props, device, TRUE) : cannot_find(label); |
756bfd01 KZ |
683 | } |
684 | ||
a125123f | 685 | static int swapon_by_uuid(struct swapon_ctl *ctl, const char *uuid) |
d335c9bd | 686 | { |
a125123f | 687 | char *device = mnt_resolve_tag("UUID", uuid, mntcache); |
6c44094a | 688 | return device ? do_swapon(ctl, &ctl->props, device, TRUE) : cannot_find(uuid); |
756bfd01 KZ |
689 | } |
690 | ||
e07fdac4 | 691 | /* -o <options> or fstab */ |
6c44094a | 692 | static int parse_options(struct swap_prop *props, const char *options) |
e07fdac4 KZ |
693 | { |
694 | char *arg = NULL; | |
07332bfa | 695 | size_t argsz = 0; |
e07fdac4 | 696 | |
6c44094a KZ |
697 | assert(props); |
698 | assert(options); | |
e07fdac4 | 699 | |
87918040 | 700 | if (mnt_optstr_get_option(options, "nofail", NULL, NULL) == 0) |
6c44094a | 701 | props->no_fail = 1; |
e07fdac4 | 702 | |
07332bfa | 703 | if (mnt_optstr_get_option(options, "discard", &arg, &argsz) == 0) { |
6c44094a | 704 | props->discard |= SWAP_FLAG_DISCARD; |
e07fdac4 KZ |
705 | |
706 | if (arg) { | |
707 | /* only single-time discards are wanted */ | |
07332bfa | 708 | if (strncmp(arg, "once", argsz) == 0) |
6c44094a | 709 | props->discard |= SWAP_FLAG_DISCARD_ONCE; |
e07fdac4 KZ |
710 | |
711 | /* do discard for every released swap page */ | |
07332bfa | 712 | if (strncmp(arg, "pages", argsz) == 0) |
6c44094a KZ |
713 | props->discard |= SWAP_FLAG_DISCARD_PAGES; |
714 | } | |
e07fdac4 KZ |
715 | } |
716 | ||
717 | arg = NULL; | |
6c44094a KZ |
718 | if (mnt_optstr_get_option(options, "pri", &arg, NULL) == 0 && arg) |
719 | props->priority = atoi(arg); | |
e07fdac4 KZ |
720 | |
721 | return 0; | |
722 | } | |
723 | ||
724 | ||
9eeba70e | 725 | static int swapon_all(struct swapon_ctl *ctl) |
d335c9bd | 726 | { |
5072b90a KZ |
727 | struct libmnt_table *tb = get_fstab(); |
728 | struct libmnt_iter *itr; | |
729 | struct libmnt_fs *fs; | |
63cccae4 | 730 | int status = 0; |
63cccae4 | 731 | |
5072b90a | 732 | if (!tb) |
d335c9bd | 733 | err(EXIT_FAILURE, _("failed to parse %s"), mnt_get_fstab_path()); |
756bfd01 | 734 | |
5072b90a KZ |
735 | itr = mnt_new_iter(MNT_ITER_FORWARD); |
736 | if (!itr) | |
737 | err(EXIT_FAILURE, _("failed to initialize libmount iterator")); | |
756bfd01 | 738 | |
5072b90a KZ |
739 | while (mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) { |
740 | /* defaults */ | |
2dd3ba2c | 741 | const char *opts; |
a125123f | 742 | const char *device; |
6c44094a | 743 | struct swap_prop prop; /* per device setting */ |
1b414d89 | 744 | |
6c44094a KZ |
745 | if (mnt_fs_get_option(fs, "noauto", NULL, NULL) == 0) { |
746 | if (ctl->verbose) | |
747 | warnx(_("%s: noauto option -- ignored"), mnt_fs_get_source(fs)); | |
1b414d89 | 748 | continue; |
6c44094a KZ |
749 | } |
750 | ||
751 | /* default setting */ | |
752 | prop = ctl->props; | |
e07fdac4 | 753 | |
6c44094a | 754 | /* overwrite default by setting from fstab */ |
e07fdac4 KZ |
755 | opts = mnt_fs_get_options(fs); |
756 | if (opts) | |
6c44094a | 757 | parse_options(&prop, opts); |
5072b90a | 758 | |
6c44094a | 759 | /* convert LABEL=, UUID= etc. from fstab to device name */ |
a125123f KZ |
760 | device = mnt_resolve_spec(mnt_fs_get_source(fs), mntcache); |
761 | if (!device) { | |
6c44094a | 762 | if (!prop.no_fail) |
5072b90a | 763 | status |= cannot_find(mnt_fs_get_source(fs)); |
756bfd01 | 764 | continue; |
1b414d89 | 765 | } |
756bfd01 | 766 | |
6c44094a KZ |
767 | if (is_active_swap(device)) { |
768 | if (ctl->verbose) | |
769 | warnx(_("%s: already active -- ignored"), device); | |
770 | continue; | |
771 | } | |
772 | ||
773 | if (prop.no_fail && access(device, R_OK) != 0) { | |
774 | if (ctl->verbose) | |
9e930041 | 775 | warnx(_("%s: inaccessible -- ignored"), device); |
6c44094a KZ |
776 | continue; |
777 | } | |
778 | ||
779 | /* swapon */ | |
780 | status |= do_swapon(ctl, &prop, device, TRUE); | |
756bfd01 | 781 | } |
756bfd01 | 782 | |
5072b90a | 783 | mnt_free_iter(itr); |
756bfd01 KZ |
784 | return status; |
785 | } | |
786 | ||
e07fdac4 | 787 | |
6e1eda6f | 788 | static void __attribute__((__noreturn__)) usage(void) |
8b0d5341 | 789 | { |
6e1eda6f | 790 | FILE *out = stdout; |
e09bd8d0 | 791 | size_t i; |
6e1eda6f | 792 | |
8b0d5341 | 793 | fputs(USAGE_HEADER, out); |
8b0d5341 KZ |
794 | fprintf(out, _(" %s [options] [<spec>]\n"), program_invocation_short_name); |
795 | ||
451dbcfa BS |
796 | fputs(USAGE_SEPARATOR, out); |
797 | fputs(_("Enable devices and files for paging and swapping.\n"), out); | |
798 | ||
8b0d5341 | 799 | fputs(USAGE_OPTIONS, out); |
6ee8e194 BS |
800 | fputs(_(" -a, --all enable all swaps from /etc/fstab\n"), out); |
801 | fputs(_(" -d, --discard[=<policy>] enable swap discards, if supported by device\n"), out); | |
802 | fputs(_(" -e, --ifexists silently skip devices that do not exist\n"), out); | |
803 | fputs(_(" -f, --fixpgsz reinitialize the swap space if necessary\n"), out); | |
804 | fputs(_(" -o, --options <list> comma-separated list of swap options\n"), out); | |
805 | fputs(_(" -p, --priority <prio> specify the priority of the swap device\n"), out); | |
806 | fputs(_(" -s, --summary display summary about used swap devices (DEPRECATED)\n"), out); | |
807 | fputs(_(" --show[=<columns>] display summary in definable table\n"), out); | |
808 | fputs(_(" --noheadings don't print table heading (with --show)\n"), out); | |
809 | fputs(_(" --raw use the raw output format (with --show)\n"), out); | |
810 | fputs(_(" --bytes display swap size in bytes in --show output\n"), out); | |
811 | fputs(_(" -v, --verbose verbose mode\n"), out); | |
8b0d5341 KZ |
812 | |
813 | fputs(USAGE_SEPARATOR, out); | |
f45f3ec3 | 814 | printf(USAGE_HELP_OPTIONS(26)); |
8b0d5341 KZ |
815 | |
816 | fputs(_("\nThe <spec> parameter:\n" \ | |
9f9d0f21 KZ |
817 | " -L <label> synonym for LABEL=<label>\n" |
818 | " -U <uuid> synonym for UUID=<uuid>\n" | |
819 | " LABEL=<label> specifies device by swap area label\n" | |
820 | " UUID=<uuid> specifies device by swap area UUID\n" | |
821 | " PARTLABEL=<label> specifies device by partition label\n" | |
822 | " PARTUUID=<uuid> specifies device by partition UUID\n" | |
823 | " <device> name of device to be used\n" | |
8b0d5341 KZ |
824 | " <file> name of file to be used\n"), out); |
825 | ||
d6387c98 | 826 | fputs(_("\nAvailable discard policy types (for --discard):\n" |
54fefa07 BS |
827 | " once : only single-time area discards are issued\n" |
828 | " pages : freed pages are discarded before they are reused\n" | |
829 | "If no policy is selected, both discard types are enabled (default).\n"), out); | |
d6387c98 | 830 | |
c3a4cfc5 | 831 | fputs(USAGE_COLUMNS, out); |
a560a348 | 832 | for (i = 0; i < ARRAY_SIZE(infos); i++) |
a12124ce | 833 | fprintf(out, " %-5s %s\n", infos[i].name, _(infos[i].help)); |
e076b552 | 834 | |
f45f3ec3 | 835 | printf(USAGE_MAN_TAIL("swapon(8)")); |
6e1eda6f | 836 | exit(EXIT_SUCCESS); |
8b0d5341 KZ |
837 | } |
838 | ||
d9f07b10 KZ |
839 | int main(int argc, char *argv[]) |
840 | { | |
8b0d5341 | 841 | int status = 0, c; |
0b0c231f | 842 | size_t i; |
6c44094a | 843 | char *options = NULL; |
756bfd01 | 844 | |
e076b552 | 845 | enum { |
e07fdac4 | 846 | BYTES_OPTION = CHAR_MAX + 1, |
7ae8b469 | 847 | NOHEADINGS_OPTION, |
e07fdac4 | 848 | RAW_OPTION, |
b5b43f27 SK |
849 | SHOW_OPTION, |
850 | OPT_LIST_TYPES | |
e076b552 SK |
851 | }; |
852 | ||
8b0d5341 | 853 | static const struct option long_opts[] = { |
87918040 SK |
854 | { "priority", required_argument, NULL, 'p' }, |
855 | { "discard", optional_argument, NULL, 'd' }, | |
856 | { "ifexists", no_argument, NULL, 'e' }, | |
857 | { "options", optional_argument, NULL, 'o' }, | |
858 | { "summary", no_argument, NULL, 's' }, | |
859 | { "fixpgsz", no_argument, NULL, 'f' }, | |
860 | { "all", no_argument, NULL, 'a' }, | |
861 | { "help", no_argument, NULL, 'h' }, | |
862 | { "verbose", no_argument, NULL, 'v' }, | |
863 | { "version", no_argument, NULL, 'V' }, | |
864 | { "show", optional_argument, NULL, SHOW_OPTION }, | |
b5b43f27 | 865 | { "output-all", no_argument, NULL, OPT_LIST_TYPES }, |
87918040 SK |
866 | { "noheadings", no_argument, NULL, NOHEADINGS_OPTION }, |
867 | { "raw", no_argument, NULL, RAW_OPTION }, | |
868 | { "bytes", no_argument, NULL, BYTES_OPTION }, | |
869 | { NULL, 0, NULL, 0 } | |
8b0d5341 KZ |
870 | }; |
871 | ||
a7349ee3 | 872 | static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ |
e07fdac4 KZ |
873 | { 'a','o','s', SHOW_OPTION }, |
874 | { 'a','o', BYTES_OPTION }, | |
875 | { 'a','o', NOHEADINGS_OPTION }, | |
876 | { 'a','o', RAW_OPTION }, | |
877 | { 0 } | |
878 | }; | |
879 | int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; | |
880 | ||
6c44094a | 881 | struct swapon_ctl ctl; |
9eeba70e | 882 | |
d9f07b10 KZ |
883 | setlocale(LC_ALL, ""); |
884 | bindtextdomain(PACKAGE, LOCALEDIR); | |
885 | textdomain(PACKAGE); | |
2c308875 | 886 | close_stdout_atexit(); |
d9f07b10 | 887 | |
6c44094a KZ |
888 | memset(&ctl, 0, sizeof(struct swapon_ctl)); |
889 | ctl.props.priority = -1; | |
890 | ||
d9f07b10 KZ |
891 | mnt_init_debug(0); |
892 | mntcache = mnt_new_cache(); | |
893 | ||
e07fdac4 | 894 | while ((c = getopt_long(argc, argv, "ahd::efo:p:svVL:U:", |
8b0d5341 | 895 | long_opts, NULL)) != -1) { |
e07fdac4 KZ |
896 | |
897 | err_exclusive_options(c, long_opts, excl, excl_st); | |
898 | ||
63cccae4 KZ |
899 | switch (c) { |
900 | case 'a': /* all */ | |
9eeba70e | 901 | ctl.all = 1; |
63cccae4 | 902 | break; |
e07fdac4 | 903 | case 'o': |
6c44094a | 904 | options = optarg; |
e07fdac4 | 905 | break; |
63cccae4 | 906 | case 'p': /* priority */ |
6c44094a | 907 | ctl.props.priority = strtos16_or_err(optarg, |
9db6a749 | 908 | _("failed to parse priority")); |
63cccae4 | 909 | break; |
756bfd01 | 910 | case 'L': |
0b0c231f | 911 | add_label(optarg); |
756bfd01 KZ |
912 | break; |
913 | case 'U': | |
0b0c231f | 914 | add_uuid(optarg); |
756bfd01 | 915 | break; |
c2301380 | 916 | case 'd': |
6c44094a | 917 | ctl.props.discard |= SWAP_FLAG_DISCARD; |
d6387c98 RA |
918 | if (optarg) { |
919 | if (*optarg == '=') | |
920 | optarg++; | |
921 | ||
922 | if (strcmp(optarg, "once") == 0) | |
6c44094a | 923 | ctl.props.discard |= SWAP_FLAG_DISCARD_ONCE; |
d6387c98 | 924 | else if (strcmp(optarg, "pages") == 0) |
6c44094a | 925 | ctl.props.discard |= SWAP_FLAG_DISCARD_PAGES; |
d6387c98 RA |
926 | else |
927 | errx(EXIT_FAILURE, _("unsupported discard policy: %s"), optarg); | |
928 | } | |
c2301380 | 929 | break; |
95f1bdee | 930 | case 'e': /* ifexists */ |
6c44094a | 931 | ctl.props.no_fail = 1; |
95f1bdee | 932 | break; |
0d761944 | 933 | case 'f': |
9eeba70e | 934 | ctl.fix_page_size = 1; |
0d761944 | 935 | break; |
63cccae4 KZ |
936 | case 's': /* status report */ |
937 | status = display_summary(); | |
8b0d5341 | 938 | return status; |
63cccae4 | 939 | case 'v': /* be chatty */ |
9eeba70e | 940 | ctl.verbose = 1; |
63cccae4 | 941 | break; |
e076b552 SK |
942 | case SHOW_OPTION: |
943 | if (optarg) { | |
9eeba70e SK |
944 | ctl.ncolumns = string_to_idarray(optarg, |
945 | ctl.columns, | |
946 | ARRAY_SIZE(ctl.columns), | |
e076b552 | 947 | column_name_to_id); |
9eeba70e | 948 | if (ctl.ncolumns < 0) |
e076b552 SK |
949 | return EXIT_FAILURE; |
950 | } | |
9eeba70e | 951 | ctl.show = 1; |
e076b552 | 952 | break; |
b5b43f27 SK |
953 | case OPT_LIST_TYPES: |
954 | for (ctl.ncolumns = 0; (size_t)ctl.ncolumns < ARRAY_SIZE(infos); ctl.ncolumns++) | |
955 | ctl.columns[ctl.ncolumns] = ctl.ncolumns; | |
956 | break; | |
e076b552 | 957 | case NOHEADINGS_OPTION: |
9eeba70e | 958 | ctl.no_heading = 1; |
e076b552 SK |
959 | break; |
960 | case RAW_OPTION: | |
9eeba70e | 961 | ctl.raw = 1; |
e076b552 | 962 | break; |
7ae8b469 | 963 | case BYTES_OPTION: |
9eeba70e | 964 | ctl.bytes = 1; |
7ae8b469 | 965 | break; |
63cccae4 KZ |
966 | case 0: |
967 | break; | |
2c308875 KZ |
968 | |
969 | case 'h': /* help */ | |
970 | usage(); | |
971 | case 'V': /* version */ | |
972 | print_version(EXIT_SUCCESS); | |
63cccae4 | 973 | default: |
677ec86c | 974 | errtryhelp(EXIT_FAILURE); |
63cccae4 KZ |
975 | } |
976 | } | |
977 | argv += optind; | |
978 | ||
9eeba70e SK |
979 | if (ctl.show || (!ctl.all && !numof_labels() && !numof_uuids() && *argv == NULL)) { |
980 | if (!ctl.ncolumns) { | |
e076b552 | 981 | /* default columns */ |
9eeba70e SK |
982 | ctl.columns[ctl.ncolumns++] = COL_PATH; |
983 | ctl.columns[ctl.ncolumns++] = COL_TYPE; | |
984 | ctl.columns[ctl.ncolumns++] = COL_SIZE; | |
985 | ctl.columns[ctl.ncolumns++] = COL_USED; | |
986 | ctl.columns[ctl.ncolumns++] = COL_PRIO; | |
e076b552 | 987 | } |
9eeba70e | 988 | status = show_table(&ctl); |
e076b552 SK |
989 | return status; |
990 | } | |
991 | ||
6e1eda6f RM |
992 | if (ctl.props.no_fail && !ctl.all) { |
993 | warnx(_("bad usage")); | |
994 | errtryhelp(EXIT_FAILURE); | |
995 | } | |
95f1bdee | 996 | |
9eeba70e SK |
997 | if (ctl.all) |
998 | status |= swapon_all(&ctl); | |
63cccae4 | 999 | |
6c44094a KZ |
1000 | if (options) |
1001 | parse_options(&ctl.props, options); | |
e07fdac4 | 1002 | |
a125123f KZ |
1003 | for (i = 0; i < numof_labels(); i++) |
1004 | status |= swapon_by_label(&ctl, get_label(i)); | |
63cccae4 | 1005 | |
a125123f KZ |
1006 | for (i = 0; i < numof_uuids(); i++) |
1007 | status |= swapon_by_uuid(&ctl, get_uuid(i)); | |
1008 | ||
1009 | while (*argv != NULL) | |
6c44094a | 1010 | status |= do_swapon(&ctl, &ctl.props, *argv++, FALSE); |
63cccae4 | 1011 | |
0b0c231f | 1012 | free_tables(); |
6195f9e6 | 1013 | mnt_unref_cache(mntcache); |
d9f07b10 | 1014 | |
64b58881 | 1015 | return status; |
6dbe3af9 | 1016 | } |