Annotation of src/sbin/swapctl/swapctl.c, Revision 1.41
1.41 ! andvar 1: /* $NetBSD: swapctl.c,v 1.40 2015/10/11 23:58:16 mrg Exp $ */
1.1 mrg 2:
3: /*
1.40 mrg 4: * Copyright (c) 1996, 1997, 1999, 2015 Matthew R. Green
1.1 mrg 5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: /*
30: * swapctl command:
1.10 mrg 31: * -A add all devices listed as `sw' in /etc/fstab (also
1.13 soren 32: * (sets the dump device, if listed in fstab)
1.30 martin 33: * -D [<dev>|none] set dumpdev to <dev> or disable dumps
1.16 mrg 34: * -z show dumpdev
1.12 lukem 35: * -U remove all devices listed as `sw' in /etc/fstab.
1.32 martin 36: * -t [blk|noblk|auto]
37: * if -A or -U , add (remove) either all block device
38: * or all non-block devices, or all swap partitions
39: * -q check if any swap or dump devices are defined in
40: * /etc/fstab
1.1 mrg 41: * -a <dev> add this device
1.17 lukem 42: * -d <dev> remove this swap device
1.32 martin 43: * -f with -A -t auto, use the first swap as dump device
1.25 mrg 44: * -g use gigabytes
1.24 mrg 45: * -h use humanize_number(3) for listing
1.1 mrg 46: * -l list swap devices
1.25 mrg 47: * -m use megabytes
1.32 martin 48: * -n print actions, but do not add/remove swap or
49: * with -A/-U
50: * -o with -A -t auto only configure the first swap as dump,
51: * (similar to -f), but do not add any further swap devs
1.1 mrg 52: * -s short listing of swap devices
53: * -k use kilobytes
54: * -p <pri> use this priority
55: * -c change priority
1.2 thorpej 56: *
57: * or, if invoked as "swapon" (compatibility mode):
58: *
59: * -a all devices listed as `sw' in /etc/fstab
1.4 thorpej 60: * -t same as -t above (feature not present in old
61: * swapon(8) command)
1.2 thorpej 62: * <dev> add this device
1.1 mrg 63: */
1.22 agc 64: #include <sys/cdefs.h>
65:
66: #ifndef lint
1.41 ! andvar 67: __RCSID("$NetBSD: swapctl.c,v 1.40 2015/10/11 23:58:16 mrg Exp $");
1.22 agc 68: #endif
69:
1.1 mrg 70:
71: #include <sys/param.h>
1.39 dsl 72: #include <sys/ioctl.h>
1.4 thorpej 73: #include <sys/stat.h>
1.14 mrg 74: #include <sys/swap.h>
1.32 martin 75: #include <sys/sysctl.h>
76: #include <sys/disk.h>
77: #include <sys/disklabel.h>
1.1 mrg 78:
79: #include <unistd.h>
1.3 mikel 80: #include <err.h>
1.1 mrg 81: #include <errno.h>
82: #include <stdio.h>
83: #include <stdlib.h>
84: #include <string.h>
85: #include <fstab.h>
1.32 martin 86: #include <fcntl.h>
87: #include <util.h>
88: #include <paths.h>
1.1 mrg 89:
90: #include "swapctl.h"
91:
1.36 joerg 92: static int command;
1.2 thorpej 93:
94: /*
95: * Commands for swapctl(8). These are mutually exclusive.
96: */
1.12 lukem 97: #define CMD_A 0x01 /* process /etc/fstab for adding */
1.10 mrg 98: #define CMD_D 0x02 /* set dumpdev */
1.12 lukem 99: #define CMD_U 0x04 /* process /etc/fstab for removing */
100: #define CMD_a 0x08 /* add a swap file/device */
101: #define CMD_c 0x10 /* change priority of a swap file/device */
102: #define CMD_d 0x20 /* delete a swap file/device */
103: #define CMD_l 0x40 /* list swap files/devices */
104: #define CMD_s 0x80 /* summary of swap files/devices */
1.16 mrg 105: #define CMD_z 0x100 /* show dump device */
1.32 martin 106: #define CMD_q 0x200 /* check for dump/swap in /etc/fstab */
1.2 thorpej 107:
108: #define SET_COMMAND(cmd) \
109: do { \
110: if (command) \
111: usage(); \
112: command = (cmd); \
113: } while (0)
114:
115: /*
116: * Commands that require a "path" argument at the end of the command
117: * line, and the ones which require that none exist.
118: */
1.10 mrg 119: #define REQUIRE_PATH (CMD_D | CMD_a | CMD_c | CMD_d)
1.32 martin 120: #define REQUIRE_NOPATH (CMD_A | CMD_U | CMD_l | CMD_s | CMD_z | CMD_q)
1.2 thorpej 121:
122: /*
123: * Option flags, and the commands with which they are valid.
124: */
1.36 joerg 125: static int kflag; /* display in 1K^x blocks */
1.2 thorpej 126: #define KFLAG_CMDS (CMD_l | CMD_s)
1.25 mrg 127: #define MFLAG_CMDS (CMD_l | CMD_s)
128: #define GFLAG_CMDS (CMD_l | CMD_s)
1.2 thorpej 129:
1.36 joerg 130: static int hflag; /* display with humanize_number */
1.24 mrg 131: #define HFLAG_CMDS (CMD_l | CMD_s)
132:
1.36 joerg 133: static int pflag; /* priority was specified */
1.2 thorpej 134: #define PFLAG_CMDS (CMD_A | CMD_a | CMD_c)
135:
1.36 joerg 136: static char *tflag; /* swap device type (blk, noblk, auto) */
137: static int autoflag; /* 1, if tflag is "auto" */
1.16 mrg 138: #define TFLAG_CMDS (CMD_A | CMD_U)
1.4 thorpej 139:
1.36 joerg 140: static int fflag; /* first swap becomes dump */
1.32 martin 141: #define FFLAG_CMDS (CMD_A)
142:
1.36 joerg 143: static int oflag; /* only autoset dump device */
1.32 martin 144: #define OFLAG_CMDS (CMD_A)
145:
1.36 joerg 146: static int nflag; /* no execute, just print actions */
1.32 martin 147: #define NFLAG_CMDS (CMD_A | CMD_U)
148:
1.36 joerg 149: static int pri; /* uses 0 as default pri */
1.1 mrg 150:
1.29 christos 151: static void change_priority(char *);
152: static int add_swap(char *, int);
153: static int delete_swap(char *);
1.40 mrg 154: static int set_dumpdev1(char *);
1.29 christos 155: static void set_dumpdev(char *);
1.30 martin 156: static int get_dumpdev(void);
1.36 joerg 157: __dead static void do_fstab(int);
1.32 martin 158: static int check_fstab(void);
159: static void do_localdevs(int);
160: static void do_localdisk(const char *, int);
161: static int do_wedgesofdisk(int fd, int);
162: static int do_partitionsofdisk(const char *, int fd, int);
1.36 joerg 163: __dead static void usage(void);
164: __dead static void swapon_command(int, char **);
1.2 thorpej 165: #if 0
1.28 xtraeme 166: static void swapoff_command(int, char **);
1.2 thorpej 167: #endif
168:
1.1 mrg 169: int
1.28 xtraeme 170: main(int argc, char *argv[])
1.1 mrg 171: {
172: int c;
1.2 thorpej 173:
1.18 cgd 174: if (strcmp(getprogname(), "swapon") == 0) {
1.2 thorpej 175: swapon_command(argc, argv);
176: /* NOTREACHED */
177: }
178:
179: #if 0
1.18 cgd 180: if (strcmp(getprogname(), "swapoff") == 0) {
1.2 thorpej 181: swapoff_command(argc, argv);
182: /* NOTREACHED */
183: }
184: #endif
185:
1.32 martin 186: while ((c = getopt(argc, argv, "ADUacdfghklmnop:qst:z")) != -1) {
1.2 thorpej 187: switch (c) {
1.1 mrg 188: case 'A':
1.2 thorpej 189: SET_COMMAND(CMD_A);
1.1 mrg 190: break;
1.2 thorpej 191:
1.10 mrg 192: case 'D':
193: SET_COMMAND(CMD_D);
194: break;
195:
1.12 lukem 196: case 'U':
197: SET_COMMAND(CMD_U);
198: break;
199:
1.1 mrg 200: case 'a':
1.2 thorpej 201: SET_COMMAND(CMD_a);
1.1 mrg 202: break;
1.2 thorpej 203:
1.1 mrg 204: case 'c':
1.2 thorpej 205: SET_COMMAND(CMD_c);
1.1 mrg 206: break;
1.2 thorpej 207:
1.1 mrg 208: case 'd':
1.2 thorpej 209: SET_COMMAND(CMD_d);
1.1 mrg 210: break;
1.2 thorpej 211:
1.32 martin 212: case 'f':
213: fflag = 1;
214: break;
215:
1.25 mrg 216: case 'g':
217: kflag = 3; /* 1k ^ 3 */
218: break;
219:
1.24 mrg 220: case 'h':
221: hflag = 1;
222: break;
223:
1.25 mrg 224: case 'k':
225: kflag = 1;
226: break;
227:
1.1 mrg 228: case 'l':
1.2 thorpej 229: SET_COMMAND(CMD_l);
1.1 mrg 230: break;
1.2 thorpej 231:
1.25 mrg 232: case 'm':
233: kflag = 2; /* 1k ^ 2 */
1.1 mrg 234: break;
1.2 thorpej 235:
1.32 martin 236: case 'n':
237: nflag = 1;
238: break;
239:
240: case 'o':
241: oflag = 1;
242: break;
243:
1.1 mrg 244: case 'p':
245: pflag = 1;
1.2 thorpej 246: /* XXX strtol() */
1.1 mrg 247: pri = atoi(optarg);
248: break;
1.2 thorpej 249:
1.32 martin 250: case 'q':
251: SET_COMMAND(CMD_q);
252: break;
253:
1.1 mrg 254: case 's':
1.2 thorpej 255: SET_COMMAND(CMD_s);
1.1 mrg 256: break;
1.2 thorpej 257:
1.4 thorpej 258: case 't':
259: if (tflag != NULL)
260: usage();
261: tflag = optarg;
1.32 martin 262: if (strcmp(tflag, "auto") == 0)
263: autoflag = 1;
1.4 thorpej 264: break;
265:
1.16 mrg 266: case 'z':
267: SET_COMMAND(CMD_z);
268: break;
269:
1.2 thorpej 270: default:
271: usage();
272: /* NOTREACHED */
1.1 mrg 273: }
274: }
1.2 thorpej 275:
276: /* Did the user specify a command? */
277: if (command == 0)
1.1 mrg 278: usage();
279:
280: argv += optind;
1.2 thorpej 281: argc -= optind;
282:
283: switch (argc) {
284: case 0:
285: if (command & REQUIRE_PATH)
286: usage();
287: break;
288:
289: case 1:
290: if (command & REQUIRE_NOPATH)
291: usage();
292: break;
293:
294: default:
1.1 mrg 295: usage();
1.2 thorpej 296: }
297:
298: /* To change priority, you have to specify one. */
299: if ((command == CMD_c) && pflag == 0)
1.1 mrg 300: usage();
301:
1.41 ! andvar 302: /* -f and -o are mutually exclusive */
1.32 martin 303: if (fflag && oflag)
304: usage();
305:
1.4 thorpej 306: /* Sanity-check -t */
307: if (tflag != NULL) {
1.12 lukem 308: if (command != CMD_A && command != CMD_U)
1.4 thorpej 309: usage();
310: if (strcmp(tflag, "blk") != 0 &&
1.32 martin 311: strcmp(tflag, "noblk") != 0 &&
312: strcmp(tflag, "auto") != 0)
1.4 thorpej 313: usage();
314: }
315:
1.2 thorpej 316: /* Dispatch the command. */
317: switch (command) {
318: case CMD_l:
1.30 martin 319: if (!list_swap(pri, kflag, pflag, 0, 1, hflag))
320: exit(1);
1.2 thorpej 321: break;
322:
323: case CMD_s:
1.24 mrg 324: list_swap(pri, kflag, pflag, 0, 0, hflag);
1.2 thorpej 325: break;
326:
327: case CMD_c:
1.1 mrg 328: change_priority(argv[0]);
1.2 thorpej 329: break;
330:
331: case CMD_a:
1.12 lukem 332: if (! add_swap(argv[0], pri))
333: exit(1);
1.2 thorpej 334: break;
335:
336: case CMD_d:
1.12 lukem 337: if (! delete_swap(argv[0]))
338: exit(1);
1.2 thorpej 339: break;
340:
341: case CMD_A:
1.32 martin 342: if (autoflag)
343: do_localdevs(1);
344: else
345: do_fstab(1);
1.2 thorpej 346: break;
1.10 mrg 347:
348: case CMD_D:
349: set_dumpdev(argv[0]);
350: break;
1.12 lukem 351:
1.16 mrg 352: case CMD_z:
1.30 martin 353: if (!get_dumpdev())
354: exit(1);
1.16 mrg 355: break;
356:
1.12 lukem 357: case CMD_U:
1.32 martin 358: if (autoflag)
359: do_localdevs(0);
360: else
361: do_fstab(0);
1.12 lukem 362: break;
1.32 martin 363: case CMD_q:
364: if (check_fstab()) {
365: printf("%s: there are swap or dump devices defined in "
366: _PATH_FSTAB "\n", getprogname());
367: exit(0);
368: } else {
369: printf("%s: no swap or dump devices in "
370: _PATH_FSTAB "\n", getprogname());
371: exit(1);
372: }
1.2 thorpej 373: }
374:
375: exit(0);
376: }
377:
378: /*
379: * swapon_command: emulate the old swapon(8) program.
380: */
1.12 lukem 381: static void
1.28 xtraeme 382: swapon_command(int argc, char **argv)
1.2 thorpej 383: {
384: int ch, fiztab = 0;
385:
1.4 thorpej 386: while ((ch = getopt(argc, argv, "at:")) != -1) {
1.2 thorpej 387: switch (ch) {
388: case 'a':
389: fiztab = 1;
390: break;
1.4 thorpej 391: case 't':
392: if (tflag != NULL)
393: usage();
394: tflag = optarg;
395: break;
1.2 thorpej 396: default:
397: goto swapon_usage;
398: }
399: }
400: argc -= optind;
401: argv += optind;
402:
403: if (fiztab) {
404: if (argc)
405: goto swapon_usage;
1.4 thorpej 406: /* Sanity-check -t */
407: if (tflag != NULL) {
408: if (strcmp(tflag, "blk") != 0 &&
409: strcmp(tflag, "noblk") != 0)
410: usage();
411: }
1.12 lukem 412: do_fstab(1);
1.2 thorpej 413: exit(0);
1.4 thorpej 414: } else if (argc == 0 || tflag != NULL)
1.2 thorpej 415: goto swapon_usage;
416:
417: while (argc) {
1.12 lukem 418: if (! add_swap(argv[0], pri))
419: exit(1);
1.2 thorpej 420: argc--;
421: argv++;
422: }
1.1 mrg 423: exit(0);
1.2 thorpej 424: /* NOTREACHED */
425:
426: swapon_usage:
1.18 cgd 427: fprintf(stderr, "usage: %s -a [-t blk|noblk]\n", getprogname());
428: fprintf(stderr, " %s <path> ...\n", getprogname());
1.2 thorpej 429: exit(1);
1.1 mrg 430: }
431:
432: /*
433: * change_priority: change the priority of a swap device.
434: */
1.12 lukem 435: static void
1.29 christos 436: change_priority(char *path)
1.1 mrg 437: {
438:
439: if (swapctl(SWAP_CTL, path, pri) < 0)
1.30 martin 440: err(1, "%s", path);
1.1 mrg 441: }
442:
443: /*
444: * add_swap: add the pathname to the list of swap devices.
445: */
1.12 lukem 446: static int
1.29 christos 447: add_swap(char *path, int priority)
1.1 mrg 448: {
1.10 mrg 449: struct stat sb;
1.38 mlelstv 450: char buf[MAXPATHLEN];
451: char *spec;
1.10 mrg 452:
1.38 mlelstv 453: if (getfsspecname(buf, sizeof(buf), path) == NULL)
454: goto oops;
455: spec = buf;
456:
457: if (stat(spec, &sb) < 0)
1.10 mrg 458: goto oops;
459:
460: if (sb.st_mode & S_IROTH)
1.19 pooka 461: warnx("WARNING: %s is readable by the world", path);
1.10 mrg 462: if (sb.st_mode & S_IWOTH)
1.19 pooka 463: warnx("WARNING: %s is writable by the world", path);
1.1 mrg 464:
1.32 martin 465: if (fflag || oflag) {
1.38 mlelstv 466: set_dumpdev1(spec);
1.32 martin 467: if (oflag)
468: exit(0);
469: else
470: fflag = 0;
471: }
472:
473: if (nflag)
474: return 1;
475:
1.38 mlelstv 476: if (swapctl(SWAP_ON, spec, priority) < 0) {
1.10 mrg 477: oops:
1.40 mrg 478: warn("%s", path);
479: return 0;
1.12 lukem 480: }
1.40 mrg 481: return 1;
1.1 mrg 482: }
483:
484: /*
1.11 mrg 485: * delete_swap: remove the pathname to the list of swap devices.
1.1 mrg 486: */
1.12 lukem 487: static int
1.29 christos 488: delete_swap(char *path)
1.1 mrg 489: {
1.38 mlelstv 490: char buf[MAXPATHLEN];
491: char *spec;
492:
1.40 mrg 493: if (getfsspecname(buf, sizeof(buf), path) == NULL) {
494: warn("%s", path);
495: return 0;
496: }
1.38 mlelstv 497: spec = buf;
1.1 mrg 498:
1.32 martin 499: if (nflag)
500: return 1;
501:
1.40 mrg 502: if (swapctl(SWAP_OFF, spec, pri) < 0) {
503: warn("%s", path);
504: return 0;
505: }
506: return 1;
1.1 mrg 507: }
508:
1.40 mrg 509: static int
1.38 mlelstv 510: set_dumpdev1(char *spec)
1.10 mrg 511: {
1.32 martin 512: int rv = 0;
1.10 mrg 513:
1.32 martin 514: if (!nflag) {
1.38 mlelstv 515: if (strcmp(spec, "none") == 0)
1.32 martin 516: rv = swapctl(SWAP_DUMPOFF, NULL, 0);
517: else
1.38 mlelstv 518: rv = swapctl(SWAP_DUMPDEV, spec, 0);
1.32 martin 519: }
1.30 martin 520:
521: if (rv == -1)
1.40 mrg 522: warn("could not set dump device to %s", spec);
1.10 mrg 523: else
1.38 mlelstv 524: printf("%s: setting dump device to %s\n", getprogname(), spec);
1.40 mrg 525:
526: return rv == -1 ? 0 : 1;
1.38 mlelstv 527: }
528:
529: static void
530: set_dumpdev(char *path)
531: {
532: char buf[MAXPATHLEN];
533: char *spec;
534:
535: if (getfsspecname(buf, sizeof(buf), path) == NULL)
536: err(1, "%s", path);
537: spec = buf;
538:
1.40 mrg 539: if (! set_dumpdev1(spec))
540: exit(1);
1.16 mrg 541: }
542:
1.30 martin 543: static int
1.28 xtraeme 544: get_dumpdev(void)
1.16 mrg 545: {
546: dev_t dev;
547: char *name;
548:
1.30 martin 549: if (swapctl(SWAP_GETDUMPDEV, &dev, 0) == -1) {
1.16 mrg 550: warn("could not get dump device");
1.30 martin 551: return 0;
552: } else if (dev == NODEV) {
1.21 drochner 553: printf("no dump device set\n");
1.30 martin 554: return 0;
555: } else {
1.16 mrg 556: name = devname(dev, S_IFBLK);
557: printf("dump device is ");
558: if (name)
559: printf("%s\n", name);
560: else
1.34 christos 561: printf("major %llu minor %llu\n",
562: (unsigned long long)major(dev),
563: (unsigned long long)minor(dev));
1.16 mrg 564: }
1.30 martin 565: return 1;
1.10 mrg 566: }
567:
1.12 lukem 568: static void
1.32 martin 569: do_localdevs(int add)
570: {
571: size_t ressize;
572: char *disknames, *disk;
573: static const char mibname[] = "hw.disknames";
574:
575: ressize = 0;
576: if (sysctlbyname(mibname, NULL, &ressize, NULL, 0))
577: return;
578: ressize += 200; /* add some arbitrary slope */
579: disknames = malloc(ressize);
580: if (sysctlbyname(mibname, disknames, &ressize, NULL, 0) == 0) {
581: for (disk = strtok(disknames, " "); disk;
582: disk = strtok(NULL, " "))
583: do_localdisk(disk, add);
584: }
585: free(disknames);
586: }
587:
588: static void
589: do_localdisk(const char *disk, int add)
590: {
591: int fd;
592: char dvname[MAXPATHLEN];
593:
594: if ((fd = opendisk(disk, O_RDONLY, dvname, sizeof(dvname), 0)) == -1)
595: return;
596:
597: if (!do_wedgesofdisk(fd, add))
598: do_partitionsofdisk(disk, fd, add);
599:
600: close(fd);
601: }
602:
603: static int
604: do_wedgesofdisk(int fd, int add)
605: {
606: char devicename[MAXPATHLEN];
607: struct dkwedge_info *dkw;
608: struct dkwedge_list dkwl;
609: size_t bufsize;
610: u_int i;
611:
612: dkw = NULL;
613: dkwl.dkwl_buf = dkw;
614: dkwl.dkwl_bufsize = 0;
615:
616: for (;;) {
617: if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1)
618: return 0;
619: if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied)
620: break;
621: bufsize = dkwl.dkwl_nwedges * sizeof(*dkw);
622: if (dkwl.dkwl_bufsize < bufsize) {
623: dkw = realloc(dkwl.dkwl_buf, bufsize);
624: if (dkw == NULL)
625: return 0;
626: dkwl.dkwl_buf = dkw;
627: dkwl.dkwl_bufsize = bufsize;
628: }
629: }
630:
631: for (i = 0; i < dkwl.dkwl_ncopied; i++) {
632: if (strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) != 0)
633: continue;
634: snprintf(devicename, sizeof(devicename), "%s%s", _PATH_DEV,
635: dkw[i].dkw_devname);
636: devicename[sizeof(devicename)-1] = '\0';
637:
638: if (add) {
639: if (add_swap(devicename, pri)) {
640: printf(
641: "%s: adding %s as swap device at priority 0\n",
642: getprogname(), devicename);
643: }
644: } else {
645: if (delete_swap(devicename)) {
646: printf(
647: "%s: removing %s as swap device\n",
648: getprogname(), devicename);
649: }
650: }
651:
652: }
653:
654: free(dkw);
655: return dkwl.dkwl_nwedges != 0;
656: }
657:
658: static int
659: do_partitionsofdisk(const char *prefix, int fd, int add)
660: {
661: char devicename[MAXPATHLEN];
662: struct disklabel lab;
663: uint i;
664:
665: if (ioctl(fd, DIOCGDINFO, &lab) != 0)
666: return 0;
667:
668: for (i = 0; i < lab.d_npartitions; i++) {
669: if (lab.d_partitions[i].p_fstype != FS_SWAP)
670: continue;
671: snprintf(devicename, sizeof(devicename), "%s%s%c", _PATH_DEV,
672: prefix, 'a'+i);
673: devicename[sizeof(devicename)-1] = '\0';
674:
675: if (add) {
676: if (add_swap(devicename, pri)) {
677: printf(
678: "%s: adding %s as swap device at priority 0\n",
679: getprogname(), devicename);
680: }
681: } else {
682: if (delete_swap(devicename)) {
683: printf(
684: "%s: removing %s as swap device\n",
685: getprogname(), devicename);
686: }
687: }
688: }
689:
690: return 1;
691: }
692:
693: static int
694: check_fstab(void)
695: {
696: struct fstab *fp;
697:
698: while ((fp = getfsent()) != NULL) {
699: if (strcmp(fp->fs_type, "dp") == 0)
700: return 1;
701:
702: if (strcmp(fp->fs_type, "sw") == 0)
703: return 1;
704: }
705:
706: return 0;
707: }
708:
709: static void
1.28 xtraeme 710: do_fstab(int add)
1.1 mrg 711: {
712: struct fstab *fp;
713: char *s;
714: long priority;
1.4 thorpej 715: struct stat st;
716: int isblk;
1.35 apb 717: int success = 0; /* set to 1 after a successful operation */
718: int error = 0; /* set to 1 after an error */
1.27 lukem 719:
720: #ifdef RESCUEDIR
721: #define PATH_MOUNT RESCUEDIR "/mount_nfs"
722: #define PATH_UMOUNT RESCUEDIR "/umount"
723: #else
1.12 lukem 724: #define PATH_MOUNT "/sbin/mount_nfs"
725: #define PATH_UMOUNT "/sbin/umount"
1.27 lukem 726: #endif
727:
1.12 lukem 728: char cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2];
1.1 mrg 729:
730: #define PRIORITYEQ "priority="
731: #define NFSMNTPT "nfsmntpt="
1.5 mikel 732: while ((fp = getfsent()) != NULL) {
1.37 christos 733: char buf[MAXPATHLEN];
734: char *spec, *fsspec;
1.1 mrg 735:
1.37 christos 736: if (getfsspecname(buf, sizeof(buf), fp->fs_spec) == NULL) {
737: warn("%s", buf);
738: continue;
739: }
740: fsspec = spec = buf;
1.12 lukem 741: cmd[0] = '\0';
1.10 mrg 742:
1.12 lukem 743: if (strcmp(fp->fs_type, "dp") == 0 && add) {
1.38 mlelstv 744: set_dumpdev1(spec);
1.10 mrg 745: continue;
746: }
747:
1.1 mrg 748: if (strcmp(fp->fs_type, "sw") != 0)
749: continue;
1.20 jdolecek 750:
751: /* handle dp as mnt option */
752: if (strstr(fp->fs_mntops, "dp") && add)
1.38 mlelstv 753: set_dumpdev1(spec);
1.20 jdolecek 754:
1.4 thorpej 755: isblk = 0;
1.1 mrg 756:
1.5 mikel 757: if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) {
1.1 mrg 758: s += sizeof(PRIORITYEQ) - 1;
759: priority = atol(s);
760: } else
761: priority = pri;
762:
1.5 mikel 763: if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) {
1.12 lukem 764: char *t;
1.1 mrg 765:
1.4 thorpej 766: /*
767: * Skip this song and dance if we're only
768: * doing block devices.
769: */
1.12 lukem 770: if (tflag != NULL && strcmp(tflag, "blk") == 0)
1.4 thorpej 771: continue;
772:
1.1 mrg 773: t = strpbrk(s, ",");
774: if (t != 0)
775: *t = '\0';
776: spec = strdup(s + strlen(NFSMNTPT));
777: if (t != 0)
778: *t = ',';
779:
780: if (spec == NULL)
781: errx(1, "Out of memory");
782:
783: if (strlen(spec) == 0) {
784: warnx("empty mountpoint");
1.28 xtraeme 785: free(spec);
1.1 mrg 786: continue;
787: }
1.12 lukem 788: if (add) {
789: snprintf(cmd, sizeof(cmd), "%s %s %s",
1.37 christos 790: PATH_MOUNT, fsspec, spec);
1.12 lukem 791: if (system(cmd) != 0) {
1.37 christos 792: warnx("%s: mount failed", fsspec);
1.12 lukem 793: continue;
794: }
795: } else {
796: snprintf(cmd, sizeof(cmd), "%s %s",
1.37 christos 797: PATH_UMOUNT, fsspec);
1.1 mrg 798: }
1.4 thorpej 799: } else {
800: /*
801: * Determine blk-ness.
802: */
803: if (stat(spec, &st) < 0) {
1.15 itojun 804: warn("%s", spec);
1.4 thorpej 805: continue;
806: }
807: if (S_ISBLK(st.st_mode))
808: isblk = 1;
809: }
810:
811: /*
812: * Skip this type if we're told to.
813: */
814: if (tflag != NULL) {
815: if (strcmp(tflag, "blk") == 0 && isblk == 0)
816: continue;
817: if (strcmp(tflag, "noblk") == 0 && isblk == 1)
818: continue;
1.1 mrg 819: }
820:
1.12 lukem 821: if (add) {
822: if (add_swap(spec, (int)priority)) {
1.35 apb 823: success = 1;
1.12 lukem 824: printf(
825: "%s: adding %s as swap device at priority %d\n",
1.37 christos 826: getprogname(), fsspec, (int)priority);
1.35 apb 827: } else {
828: error = 1;
829: fprintf(stderr,
830: "%s: failed to add %s as swap device\n",
1.37 christos 831: getprogname(), fsspec);
1.12 lukem 832: }
833: } else {
834: if (delete_swap(spec)) {
1.35 apb 835: success = 1;
1.12 lukem 836: printf(
837: "%s: removing %s as swap device\n",
1.37 christos 838: getprogname(), fsspec);
1.35 apb 839: } else {
840: error = 1;
841: fprintf(stderr,
842: "%s: failed to remove %s as swap device\n",
1.37 christos 843: getprogname(), fsspec);
1.12 lukem 844: }
845: if (cmd[0]) {
846: if (system(cmd) != 0) {
1.37 christos 847: warnx("%s: umount failed", fsspec);
1.35 apb 848: error = 1;
1.12 lukem 849: continue;
850: }
851: }
1.8 mrg 852: }
1.1 mrg 853:
1.37 christos 854: if (spec != fsspec)
1.28 xtraeme 855: free(spec);
1.1 mrg 856: }
1.35 apb 857: if (error)
1.8 mrg 858: exit(1);
1.35 apb 859: else if (success)
860: exit(0);
861: else
862: exit(2); /* not really an error, but no swap devices found */
1.1 mrg 863: }
864:
1.12 lukem 865: static void
1.28 xtraeme 866: usage(void)
1.1 mrg 867: {
1.18 cgd 868: const char *progname = getprogname();
1.1 mrg 869:
1.32 martin 870: fprintf(stderr, "usage: %s -A [-f|-o] [-n] [-p priority] "
871: "[-t blk|noblk|auto]\n", progname);
1.18 cgd 872: fprintf(stderr, " %s -a [-p priority] path\n", progname);
1.32 martin 873: fprintf(stderr, " %s -q\n", progname);
1.18 cgd 874: fprintf(stderr, " %s -c -p priority path\n", progname);
1.31 wiz 875: fprintf(stderr, " %s -D dumpdev|none\n", progname);
1.18 cgd 876: fprintf(stderr, " %s -d path\n", progname);
1.25 mrg 877: fprintf(stderr, " %s -l | -s [-k|-m|-g|-h]\n", progname);
1.32 martin 878: fprintf(stderr, " %s -U [-n] [-t blk|noblk|auto]\n", progname);
1.26 cjep 879: fprintf(stderr, " %s -z\n", progname);
1.1 mrg 880: exit(1);
881: }
CVSweb <webmaster@jp.NetBSD.org>