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