]>
Commit | Line | Data |
---|---|---|
fd6b7a7f KZ |
1 | #include <stdlib.h> |
2 | #include <stdio.h> | |
3 | #include <getopt.h> | |
4 | #include <string.h> | |
5 | #include <mntent.h> | |
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 | |
3399a218 MK |
17 | #include "bitops.h" |
18 | #include "blkdev.h" | |
7eda085c | 19 | #include "nls.h" |
4e270e3f | 20 | #include "pathnames.h" |
3399a218 | 21 | #include "swapheader.h" |
bfbb12d2 | 22 | #include "xalloc.h" |
eb76ca98 | 23 | #include "c.h" |
efb8854f | 24 | #include "closestream.h" |
167eaed7 | 25 | |
0b0c231f KZ |
26 | #include "swapon-common.h" |
27 | ||
6274b987 KC |
28 | #define PATH_MKSWAP "/sbin/mkswap" |
29 | ||
ffa63a3d MF |
30 | #ifdef HAVE_SYS_SWAP_H |
31 | # include <sys/swap.h> | |
32 | #endif | |
33 | ||
c2301380 HD |
34 | #ifndef SWAP_FLAG_DISCARD |
35 | # define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */ | |
36 | #endif | |
37 | ||
9514a612 KZ |
38 | #ifndef SWAP_FLAG_PREFER |
39 | # define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ | |
40 | #endif | |
41 | ||
42 | #ifndef SWAP_FLAG_PRIO_MASK | |
43 | # define SWAP_FLAG_PRIO_MASK 0x7fff | |
44 | #endif | |
45 | ||
46 | #ifndef SWAP_FLAG_PRIO_SHIFT | |
47 | # define SWAP_FLAG_PRIO_SHIFT 0 | |
48 | #endif | |
49 | ||
ffa63a3d MF |
50 | #ifndef SWAPON_HAS_TWO_ARGS |
51 | /* libc is insane, let's call the kernel */ | |
52 | # include <sys/syscall.h> | |
53 | # define swapon(path, flags) syscall(SYS_swapon, path, flags) | |
ffa63a3d MF |
54 | #endif |
55 | ||
fd6b7a7f KZ |
56 | #define streq(s, t) (strcmp ((s), (t)) == 0) |
57 | ||
63cccae4 | 58 | #define QUIET 1 |
12ac2bbe | 59 | #define CANONIC 1 |
63cccae4 | 60 | |
3399a218 MK |
61 | #define MAX_PAGESIZE (64 * 1024) |
62 | ||
e8be80dd KZ |
63 | enum { |
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 |
71 | static int all; |
72 | static int priority = -1; /* non-prioritized swap by default */ | |
73 | static int discard; | |
6dbe3af9 | 74 | |
95f1bdee | 75 | /* If true, don't complain if the device/file doesn't exist */ |
16ff9813 TK |
76 | static int ifexists; |
77 | static int fixpgsz; | |
81772d3c | 78 | |
16ff9813 TK |
79 | static int verbose; |
80 | static char *progname; | |
95f1bdee | 81 | |
16ff9813 | 82 | static const struct option longswaponopts[] = { |
63cccae4 KZ |
83 | /* swapon only */ |
84 | { "priority", required_argument, 0, 'p' }, | |
c2301380 | 85 | { "discard", 0, 0, 'd' }, |
95f1bdee | 86 | { "ifexists", 0, 0, 'e' }, |
63cccae4 | 87 | { "summary", 0, 0, 's' }, |
0d761944 | 88 | { "fixpgsz", 0, 0, 'f' }, |
63cccae4 KZ |
89 | /* also for swapoff */ |
90 | { "all", 0, 0, 'a' }, | |
91 | { "help", 0, 0, 'h' }, | |
92 | { "verbose", 0, 0, 'v' }, | |
93 | { "version", 0, 0, 'V' }, | |
94 | { NULL, 0, 0, 0 } | |
6dbe3af9 KZ |
95 | }; |
96 | ||
240e20b5 | 97 | #define PRINT_USAGE_SPECIAL(_fp) \ |
53e20cec KZ |
98 | fputs(_("\nThe <spec> parameter:\n" \ |
99 | " -L <label> LABEL of device to be used\n" \ | |
100 | " -U <uuid> UUID of device to be used\n" \ | |
101 | " LABEL=<label> LABEL of device to be used\n" \ | |
102 | " UUID=<uuid> UUID of device to be used\n" \ | |
103 | " <device> name of device to be used\n" \ | |
104 | " <file> name of file to be used\n\n"), _fp) | |
240e20b5 | 105 | |
6dbe3af9 | 106 | static void |
53e20cec KZ |
107 | swapon_usage(FILE *out, int n) { |
108 | fputs(_("\nUsage:\n"), out); | |
109 | fprintf(out, _(" %s [options] [<spec>]\n"), progname); | |
110 | ||
111 | fputs(_("\nOptions:\n"), out); | |
112 | fputs(_(" -a, --all enable all swaps from /etc/fstab\n" | |
113 | " -d, --discard discard freed pages before they are reused\n" | |
114 | " -e, --ifexists silently skip devices that do not exis\n" | |
115 | " -f, --fixpgsz reinitialize the swap space if necessary\n" | |
116 | " -h, --help display help and exit\n" | |
f9bd0858 | 117 | " -p, --priority <prio> specify the priority of the swap device\n" |
53e20cec KZ |
118 | " -s, --summary display summary about used swap devices and exit\n" |
119 | " -v, --verbose verbose mode\n" | |
120 | " -V, --version display version and exit\n"), out); | |
121 | ||
122 | PRINT_USAGE_SPECIAL(out); | |
240e20b5 | 123 | |
63cccae4 KZ |
124 | exit(n); |
125 | } | |
126 | ||
fd6b7a7f KZ |
127 | static int |
128 | display_summary(void) | |
129 | { | |
5072b90a | 130 | struct libmnt_table *st = get_swaps(); |
64b58881 KZ |
131 | struct libmnt_iter *itr; |
132 | struct libmnt_fs *fs; | |
fd6b7a7f | 133 | |
64b58881 | 134 | if (!st) |
57a60bf0 | 135 | return -1; |
e8f26419 | 136 | |
64b58881 KZ |
137 | itr = mnt_new_iter(MNT_ITER_FORWARD); |
138 | if (!itr) | |
139 | err(EXIT_FAILURE, _("failed to initialize libmount iterator")); | |
57a60bf0 | 140 | |
64b58881 KZ |
141 | if (mnt_table_get_nents(st) > 0) |
142 | printf(_("%-39s\tType\tSize\tUsed\tPriority\n"), _("Filename")); | |
143 | ||
144 | while (mnt_table_next_fs(st, itr, &fs) == 0) { | |
145 | printf("%-39s\t%s\t%jd\t%jd\t%d\n", | |
146 | mnt_fs_get_source(fs), | |
147 | mnt_fs_get_swaptype(fs), | |
148 | mnt_fs_get_size(fs), | |
149 | mnt_fs_get_usedsize(fs), | |
150 | mnt_fs_get_priority(fs)); | |
57a60bf0 | 151 | } |
fd6b7a7f | 152 | |
64b58881 KZ |
153 | mnt_free_iter(itr); |
154 | return 0; | |
fd6b7a7f KZ |
155 | } |
156 | ||
6274b987 KC |
157 | /* calls mkswap */ |
158 | static int | |
b5b2c388 KZ |
159 | swap_reinitialize(const char *device, const char *label, const char *uuid) |
160 | { | |
6274b987 KC |
161 | pid_t pid; |
162 | int status, ret; | |
163 | char *cmd[7]; | |
164 | int idx=0; | |
165 | ||
0d761944 KZ |
166 | warnx(_("%s: reinitializing the swap."), device); |
167 | ||
6274b987 KC |
168 | switch((pid=fork())) { |
169 | case -1: /* fork error */ | |
d51d05d3 | 170 | warn(_("fork failed")); |
6274b987 KC |
171 | return -1; |
172 | ||
173 | case 0: /* child */ | |
174 | cmd[idx++] = PATH_MKSWAP; | |
175 | if (label && *label) { | |
176 | cmd[idx++] = "-L"; | |
177 | cmd[idx++] = (char *) label; | |
178 | } | |
179 | if (uuid && *uuid) { | |
180 | cmd[idx++] = "-U"; | |
181 | cmd[idx++] = (char *) uuid; | |
182 | } | |
183 | cmd[idx++] = (char *) device; | |
184 | cmd[idx++] = NULL; | |
185 | execv(cmd[0], cmd); | |
d51d05d3 | 186 | err(EXIT_FAILURE, _("execv failed")); |
6274b987 KC |
187 | |
188 | default: /* parent */ | |
189 | do { | |
190 | if ((ret = waitpid(pid, &status, 0)) < 0 | |
191 | && errno == EINTR) | |
192 | continue; | |
193 | else if (ret < 0) { | |
d51d05d3 | 194 | warn(_("waitpid failed")); |
6274b987 KC |
195 | return -1; |
196 | } | |
197 | } while (0); | |
198 | ||
199 | /* mkswap returns: 0=suss, 1=error */ | |
200 | if (WIFEXITED(status) && WEXITSTATUS(status)==0) | |
201 | return 0; /* ok */ | |
f8ff4ebb | 202 | break; |
6274b987 KC |
203 | } |
204 | return -1; /* error */ | |
205 | } | |
206 | ||
617d8a3b KZ |
207 | static int |
208 | swap_rewrite_signature(const char *devname, unsigned int pagesize) | |
209 | { | |
210 | int fd, rc = -1; | |
211 | ||
212 | fd = open(devname, O_WRONLY); | |
213 | if (fd == -1) { | |
214 | warn(_("%s: open failed"), devname); | |
215 | return -1; | |
216 | } | |
217 | ||
5dd53f43 KZ |
218 | if (lseek(fd, pagesize - SWAP_SIGNATURE_SZ, SEEK_SET) < 0) { |
219 | warn(_("%s: lseek failed"), devname); | |
617d8a3b | 220 | goto err; |
5dd53f43 | 221 | } |
617d8a3b KZ |
222 | |
223 | if (write(fd, (void *) SWAP_SIGNATURE, | |
5dd53f43 KZ |
224 | SWAP_SIGNATURE_SZ) != SWAP_SIGNATURE_SZ) { |
225 | warn(_("%s: write signature failed"), devname); | |
617d8a3b | 226 | goto err; |
5dd53f43 | 227 | } |
617d8a3b KZ |
228 | |
229 | rc = 0; | |
230 | err: | |
231 | close(fd); | |
232 | return rc; | |
233 | } | |
234 | ||
e8be80dd KZ |
235 | static int |
236 | swap_detect_signature(const char *buf, int *sig) | |
3399a218 | 237 | { |
e8be80dd KZ |
238 | if (memcmp(buf, "SWAP-SPACE", 10) == 0 || |
239 | memcmp(buf, "SWAPSPACE2", 10) == 0) | |
240 | *sig = SIG_SWAPSPACE; | |
241 | ||
242 | else if (memcmp(buf, "S1SUSPEND", 9) == 0 || | |
243 | memcmp(buf, "S2SUSPEND", 9) == 0 || | |
244 | memcmp(buf, "ULSUSPEND", 9) == 0 || | |
5a16af58 KZ |
245 | memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0 || |
246 | memcmp(buf, "LINHIB0001", 10) == 0) | |
e8be80dd KZ |
247 | *sig = SIG_SWSUSPEND; |
248 | else | |
249 | return 0; | |
3399a218 | 250 | |
e8be80dd | 251 | return 1; |
3399a218 MK |
252 | } |
253 | ||
e8be80dd KZ |
254 | static char * |
255 | swap_get_header(int fd, int *sig, unsigned int *pagesize) | |
3399a218 | 256 | { |
3399a218 | 257 | char *buf; |
e8be80dd KZ |
258 | ssize_t datasz; |
259 | unsigned int page; | |
3399a218 | 260 | |
e8be80dd KZ |
261 | *pagesize = 0; |
262 | *sig = 0; | |
3399a218 | 263 | |
bfbb12d2 | 264 | buf = xmalloc(MAX_PAGESIZE); |
3399a218 MK |
265 | |
266 | datasz = read(fd, buf, MAX_PAGESIZE); | |
e8be80dd KZ |
267 | if (datasz == (ssize_t) -1) |
268 | goto err; | |
3399a218 MK |
269 | |
270 | for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) { | |
271 | /* skip 32k pagesize since this does not seem to | |
272 | * be supported */ | |
273 | if (page == 0x8000) | |
274 | continue; | |
275 | /* the smallest swap area is PAGE_SIZE*10, it means | |
276 | * 40k, that's less than MAX_PAGESIZE */ | |
24f010e8 | 277 | if (datasz < 0 || (size_t) datasz < (page - SWAP_SIGNATURE_SZ)) |
3399a218 | 278 | break; |
617d8a3b | 279 | if (swap_detect_signature(buf + page - SWAP_SIGNATURE_SZ, sig)) { |
e8be80dd | 280 | *pagesize = page; |
3399a218 MK |
281 | break; |
282 | } | |
283 | } | |
284 | ||
e8be80dd KZ |
285 | if (*pagesize) |
286 | return buf; | |
3399a218 | 287 | err: |
e8be80dd KZ |
288 | free(buf); |
289 | return NULL; | |
290 | } | |
291 | ||
292 | /* returns real size of swap space */ | |
293 | unsigned long long | |
294 | swap_get_size(const char *hdr, const char *devname, unsigned int pagesize) | |
295 | { | |
296 | unsigned int last_page = 0; | |
297 | int swap_version = 0; | |
298 | int flip = 0; | |
299 | struct swap_header_v1_2 *s; | |
300 | ||
301 | s = (struct swap_header_v1_2 *) hdr; | |
302 | if (s->version == 1) { | |
303 | swap_version = 1; | |
304 | last_page = s->last_page; | |
305 | } else if (swab32(s->version) == 1) { | |
306 | flip = 1; | |
307 | swap_version = 1; | |
308 | last_page = swab32(s->last_page); | |
309 | } | |
310 | if (verbose) | |
04c94441 KZ |
311 | warnx(_("%s: found swap signature: version %d, " |
312 | "page-size %d, %s byte order"), | |
e8be80dd | 313 | devname, |
e8be80dd | 314 | swap_version, |
04c94441 KZ |
315 | pagesize / 1024, |
316 | flip ? _("different") : _("same")); | |
e8be80dd | 317 | |
98e9ff61 | 318 | return ((unsigned long long) last_page + 1) * pagesize; |
3399a218 MK |
319 | } |
320 | ||
b5b2c388 KZ |
321 | void |
322 | swap_get_info(const char *hdr, char **label, char **uuid) | |
323 | { | |
324 | struct swap_header_v1_2 *s = (struct swap_header_v1_2 *) hdr; | |
325 | ||
326 | if (s && *s->volume_name && label) | |
327 | *label = xstrdup(s->volume_name); | |
328 | ||
329 | if (s && *s->uuid && uuid) { | |
330 | const unsigned char *u = s->uuid; | |
331 | char str[37]; | |
332 | ||
333 | snprintf(str, sizeof(str), | |
334 | "%02x%02x%02x%02x-" | |
335 | "%02x%02x-%02x%02x-" | |
336 | "%02x%02x-%02x%02x%02x%02x%02x%02x", | |
337 | u[0], u[1], u[2], u[3], | |
338 | u[4], u[5], u[6], u[7], | |
339 | u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]); | |
340 | *uuid = xstrdup(str); | |
341 | } | |
342 | } | |
343 | ||
63cccae4 | 344 | static int |
05c79b78 KZ |
345 | swapon_checks(const char *special) |
346 | { | |
63cccae4 | 347 | struct stat st; |
05c79b78 KZ |
348 | int fd = -1, sig; |
349 | char *hdr = NULL; | |
e8be80dd KZ |
350 | unsigned int pagesize; |
351 | unsigned long long devsize = 0; | |
63cccae4 | 352 | |
63cccae4 | 353 | if (stat(special, &st) < 0) { |
d51d05d3 | 354 | warn(_("%s: stat failed"), special); |
05c79b78 | 355 | goto err; |
63cccae4 KZ |
356 | } |
357 | ||
88530f9f KZ |
358 | /* people generally dislike this warning - now it is printed |
359 | only when `verbose' is set */ | |
360 | if (verbose) { | |
361 | int permMask = (S_ISBLK(st.st_mode) ? 07007 : 07077); | |
362 | ||
d51d05d3 KZ |
363 | if ((st.st_mode & permMask) != 0) |
364 | warnx(_("%s: insecure permissions %04o, %04o suggested."), | |
365 | special, st.st_mode & 07777, | |
88530f9f | 366 | ~permMask & 0666); |
306c1df2 KZ |
367 | |
368 | if (S_ISREG(st.st_mode) && st.st_uid != 0) | |
369 | warnx(_("%s: insecure file owner %d, 0 (root) suggested."), | |
370 | special, st.st_uid); | |
88530f9f KZ |
371 | } |
372 | ||
373 | /* test for holes by LBT */ | |
374 | if (S_ISREG(st.st_mode)) { | |
375 | if (st.st_blocks * 512 < st.st_size) { | |
d51d05d3 KZ |
376 | warnx(_("%s: skipping - it appears to have holes."), |
377 | special); | |
05c79b78 | 378 | goto err; |
88530f9f | 379 | } |
e8be80dd KZ |
380 | devsize = st.st_size; |
381 | } | |
382 | ||
383 | fd = open(special, O_RDONLY); | |
384 | if (fd == -1) { | |
d51d05d3 | 385 | warn(_("%s: open failed"), special); |
05c79b78 | 386 | goto err; |
e8be80dd KZ |
387 | } |
388 | ||
05c79b78 KZ |
389 | if (S_ISBLK(st.st_mode) && blkdev_get_size(fd, &devsize)) { |
390 | warn(_("%s: get size failed"), special); | |
391 | goto err; | |
e8be80dd KZ |
392 | } |
393 | ||
394 | hdr = swap_get_header(fd, &sig, &pagesize); | |
395 | if (!hdr) { | |
d51d05d3 | 396 | warn(_("%s: read swap header failed"), special); |
05c79b78 | 397 | goto err; |
88530f9f KZ |
398 | } |
399 | ||
e8be80dd KZ |
400 | if (sig == SIG_SWAPSPACE && pagesize) { |
401 | unsigned long long swapsize = | |
402 | swap_get_size(hdr, special, pagesize); | |
24f010e8 KZ |
403 | int syspg = getpagesize(); |
404 | ||
3399a218 | 405 | if (verbose) |
e6b0611b | 406 | warnx(_("%s: pagesize=%d, swapsize=%llu, devsize=%llu"), |
e8be80dd KZ |
407 | special, pagesize, swapsize, devsize); |
408 | ||
409 | if (swapsize > devsize) { | |
410 | if (verbose) | |
d51d05d3 KZ |
411 | warnx(_("%s: last_page 0x%08llx is larger" |
412 | " than actual size of swapspace"), | |
e8be80dd | 413 | special, swapsize); |
24f010e8 | 414 | } else if (syspg < 0 || (unsigned) syspg != pagesize) { |
0d761944 | 415 | if (fixpgsz) { |
b5b2c388 KZ |
416 | char *label = NULL, *uuid = NULL; |
417 | int rc; | |
418 | ||
419 | swap_get_info(hdr, &label, &uuid); | |
420 | ||
93bfcc94 | 421 | warnx(_("%s: swap format pagesize does not match."), |
0d761944 | 422 | special); |
b5b2c388 KZ |
423 | rc = swap_reinitialize(special, label, uuid); |
424 | free(label); | |
425 | free(uuid); | |
426 | if (rc < 0) | |
0d761944 KZ |
427 | goto err; |
428 | } else | |
93bfcc94 KZ |
429 | warnx(_("%s: swap format pagesize does not match. " |
430 | "(Use --fixpgsz to reinitialize it.)"), | |
0d761944 | 431 | special); |
e8be80dd KZ |
432 | } |
433 | } else if (sig == SIG_SWSUSPEND) { | |
434 | /* We have to reinitialize swap with old (=useless) software suspend | |
435 | * data. The problem is that if we don't do it, then we get data | |
436 | * corruption the next time an attempt at unsuspending is made. | |
437 | */ | |
d51d05d3 | 438 | warnx(_("%s: software suspend data detected. " |
617d8a3b | 439 | "Rewriting the swap signature."), |
d51d05d3 | 440 | special); |
617d8a3b | 441 | if (swap_rewrite_signature(special, pagesize) < 0) |
05c79b78 | 442 | goto err; |
6274b987 KC |
443 | } |
444 | ||
05c79b78 KZ |
445 | free(hdr); |
446 | close(fd); | |
447 | return 0; | |
05c79b78 KZ |
448 | err: |
449 | if (fd != -1) | |
450 | close(fd); | |
451 | free(hdr); | |
452 | return -1; | |
453 | } | |
63cccae4 | 454 | |
05c79b78 | 455 | static int |
c2301380 | 456 | do_swapon(const char *orig_special, int prio, int fl_discard, int canonic) { |
05c79b78 KZ |
457 | int status; |
458 | const char *special = orig_special; | |
459 | int flags = 0; | |
63cccae4 | 460 | |
05c79b78 KZ |
461 | if (verbose) |
462 | printf(_("%s on %s\n"), progname, orig_special); | |
463 | ||
464 | if (!canonic) { | |
e5157fc9 | 465 | special = mnt_resolve_spec(orig_special, mntcache); |
05c79b78 KZ |
466 | if (!special) |
467 | return cannot_find(orig_special); | |
63cccae4 | 468 | } |
ffa63a3d | 469 | |
05c79b78 KZ |
470 | if (swapon_checks(special)) |
471 | return -1; | |
472 | ||
473 | #ifdef SWAP_FLAG_PREFER | |
474 | if (prio >= 0) { | |
475 | if (prio > SWAP_FLAG_PRIO_MASK) | |
476 | prio = SWAP_FLAG_PRIO_MASK; | |
477 | flags = SWAP_FLAG_PREFER | |
478 | | ((prio & SWAP_FLAG_PRIO_MASK) | |
479 | << SWAP_FLAG_PRIO_SHIFT); | |
480 | } | |
481 | #endif | |
c2301380 HD |
482 | if (fl_discard) |
483 | flags |= SWAP_FLAG_DISCARD; | |
484 | ||
05c79b78 | 485 | status = swapon(special, flags); |
d51d05d3 KZ |
486 | if (status < 0) |
487 | warn(_("%s: swapon failed"), orig_special); | |
63cccae4 KZ |
488 | |
489 | return status; | |
490 | } | |
491 | ||
756bfd01 | 492 | static int |
c2301380 | 493 | swapon_by_label(const char *label, int prio, int dsc) { |
e5157fc9 | 494 | const char *special = mnt_resolve_tag("LABEL", label, mntcache); |
c2301380 HD |
495 | return special ? do_swapon(special, prio, dsc, CANONIC) : |
496 | cannot_find(label); | |
756bfd01 KZ |
497 | } |
498 | ||
499 | static int | |
c2301380 | 500 | swapon_by_uuid(const char *uuid, int prio, int dsc) { |
e5157fc9 | 501 | const char *special = mnt_resolve_tag("UUID", uuid, mntcache); |
c2301380 HD |
502 | return special ? do_swapon(special, prio, dsc, CANONIC) : |
503 | cannot_find(uuid); | |
756bfd01 KZ |
504 | } |
505 | ||
756bfd01 KZ |
506 | static int |
507 | swapon_all(void) { | |
5072b90a KZ |
508 | struct libmnt_table *tb = get_fstab(); |
509 | struct libmnt_iter *itr; | |
510 | struct libmnt_fs *fs; | |
63cccae4 | 511 | int status = 0; |
63cccae4 | 512 | |
5072b90a KZ |
513 | if (!tb) |
514 | err(2, _("failed to parse %s"), mnt_get_fstab_path()); | |
756bfd01 | 515 | |
5072b90a KZ |
516 | itr = mnt_new_iter(MNT_ITER_FORWARD); |
517 | if (!itr) | |
518 | err(EXIT_FAILURE, _("failed to initialize libmount iterator")); | |
756bfd01 | 519 | |
5072b90a KZ |
520 | while (mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) { |
521 | /* defaults */ | |
522 | int pri = priority, dsc = discard, nofail = ifexists; | |
523 | char *p, *src; | |
1b414d89 | 524 | |
5072b90a | 525 | if (mnt_fs_get_option(fs, "noauto", NULL, NULL) == 0) |
1b414d89 | 526 | continue; |
5072b90a KZ |
527 | if (mnt_fs_get_option(fs, "discard", NULL, NULL) == 0) |
528 | dsc = 1; | |
529 | if (mnt_fs_get_option(fs, "nofail", NULL, NULL) == 0) | |
530 | nofail = 1; | |
531 | if (mnt_fs_get_option(fs, "pri", &p, NULL) == 0 && p) | |
532 | pri = atoi(p); | |
533 | ||
534 | src = mnt_resolve_spec(mnt_fs_get_source(fs), mntcache); | |
535 | if (!src) { | |
a5fd3d68 | 536 | if (!nofail) |
5072b90a | 537 | status |= cannot_find(mnt_fs_get_source(fs)); |
756bfd01 | 538 | continue; |
1b414d89 | 539 | } |
756bfd01 | 540 | |
5072b90a KZ |
541 | if (!is_active_swap(src) && |
542 | (!nofail || !access(src, R_OK))) | |
543 | status |= do_swapon(src, pri, dsc, CANONIC); | |
756bfd01 | 544 | } |
756bfd01 | 545 | |
5072b90a | 546 | mnt_free_iter(itr); |
756bfd01 KZ |
547 | return status; |
548 | } | |
549 | ||
756bfd01 KZ |
550 | static int |
551 | main_swapon(int argc, char *argv[]) { | |
552 | int status = 0; | |
0b0c231f KZ |
553 | int c; |
554 | size_t i; | |
756bfd01 | 555 | |
c2301380 | 556 | while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:", |
756bfd01 | 557 | longswaponopts, NULL)) != -1) { |
63cccae4 KZ |
558 | switch (c) { |
559 | case 'a': /* all */ | |
560 | ++all; | |
561 | break; | |
562 | case 'h': /* help */ | |
563 | swapon_usage(stdout, 0); | |
564 | break; | |
565 | case 'p': /* priority */ | |
566 | priority = atoi(optarg); | |
567 | break; | |
756bfd01 | 568 | case 'L': |
0b0c231f | 569 | add_label(optarg); |
756bfd01 KZ |
570 | break; |
571 | case 'U': | |
0b0c231f | 572 | add_uuid(optarg); |
756bfd01 | 573 | break; |
c2301380 HD |
574 | case 'd': |
575 | discard = 1; | |
576 | break; | |
95f1bdee KZ |
577 | case 'e': /* ifexists */ |
578 | ifexists = 1; | |
579 | break; | |
0d761944 KZ |
580 | case 'f': |
581 | fixpgsz = 1; | |
582 | break; | |
63cccae4 KZ |
583 | case 's': /* status report */ |
584 | status = display_summary(); | |
585 | exit(status); | |
586 | case 'v': /* be chatty */ | |
587 | ++verbose; | |
588 | break; | |
589 | case 'V': /* version */ | |
e6b0611b | 590 | printf(_("%s (%s)\n"), progname, PACKAGE_STRING); |
8fdf2bf7 | 591 | exit(EXIT_SUCCESS); |
63cccae4 KZ |
592 | case 0: |
593 | break; | |
594 | case '?': | |
595 | default: | |
596 | swapon_usage(stderr, 1); | |
597 | } | |
598 | } | |
599 | argv += optind; | |
600 | ||
0b0c231f | 601 | if (!all && !numof_labels() && numof_uuids() && *argv == NULL) |
63cccae4 KZ |
602 | swapon_usage(stderr, 2); |
603 | ||
756bfd01 KZ |
604 | if (ifexists && (!all || strcmp(progname, "swapon"))) |
605 | swapon_usage(stderr, 1); | |
95f1bdee | 606 | |
756bfd01 KZ |
607 | if (all) |
608 | status |= swapon_all(); | |
63cccae4 | 609 | |
0b0c231f KZ |
610 | for (i = 0; i < numof_labels(); i++) |
611 | status |= swapon_by_label(get_label(i), priority, discard); | |
63cccae4 | 612 | |
0b0c231f KZ |
613 | for (i = 0; i < numof_uuids(); i++) |
614 | status |= swapon_by_uuid(get_uuid(i), priority, discard); | |
63cccae4 KZ |
615 | |
616 | while (*argv != NULL) | |
c2301380 | 617 | status |= do_swapon(*argv++, priority, discard, !CANONIC); |
63cccae4 KZ |
618 | |
619 | return status; | |
620 | } | |
621 | ||
63cccae4 KZ |
622 | int |
623 | main(int argc, char *argv[]) { | |
63cccae4 | 624 | |
64b58881 KZ |
625 | int status; |
626 | ||
63cccae4 KZ |
627 | setlocale(LC_ALL, ""); |
628 | bindtextdomain(PACKAGE, LOCALEDIR); | |
629 | textdomain(PACKAGE); | |
efb8854f | 630 | atexit(close_stdout); |
63cccae4 | 631 | |
d51d05d3 KZ |
632 | progname = program_invocation_short_name; |
633 | if (!progname) { | |
634 | char *p = strrchr(argv[0], '/'); | |
635 | progname = p ? p+1 : argv[0]; | |
636 | } | |
63cccae4 | 637 | |
64b58881 | 638 | mnt_init_debug(0); |
e5157fc9 | 639 | mntcache = mnt_new_cache(); |
64b58881 | 640 | |
6cf8d46c | 641 | status = main_swapon(argc, argv); |
64b58881 | 642 | |
0b0c231f | 643 | free_tables(); |
64b58881 KZ |
644 | mnt_free_cache(mntcache); |
645 | return status; | |
6dbe3af9 | 646 | } |