1 /* $NetBSD: swapctl.c,v 1.43 2023/03/01 15:18:18 kre Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997, 1999, 2015 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.43 2023/03/01 15:18:18 kre 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 int 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 mutually 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 warn("%s", path); 479 return 0; 480 } 481 return 1; 482 } 483 484 /* 485 * delete_swap: remove the pathname to the list of swap devices. 486 */ 487 static int 488 delete_swap(char *path) 489 { 490 char buf[MAXPATHLEN]; 491 char *spec; 492 493 if (getfsspecname(buf, sizeof(buf), path) == NULL) { 494 warn("%s", path); 495 return 0; 496 } 497 spec = buf; 498 499 if (nflag) 500 return 1; 501 502 if (swapctl(SWAP_OFF, spec, pri) < 0) { 503 warn("%s", path); 504 return 0; 505 } 506 return 1; 507 } 508 509 static int 510 set_dumpdev1(char *spec) 511 { 512 int rv = 0; 513 514 if (!nflag) { 515 if (strcmp(spec, "none") == 0) 516 rv = swapctl(SWAP_DUMPOFF, NULL, 0); 517 else 518 rv = swapctl(SWAP_DUMPDEV, spec, 0); 519 } 520 521 if (rv == -1) 522 warn("could not set dump device to %s", spec); 523 else 524 printf("%s: setting dump device to %s\n", getprogname(), spec); 525 526 return rv == -1 ? 0 : 1; 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 539 if (! set_dumpdev1(spec)) 540 exit(1); 541 } 542 543 static int 544 get_dumpdev(void) 545 { 546 dev_t dev; 547 char *name; 548 549 if (swapctl(SWAP_GETDUMPDEV, &dev, 0) == -1) { 550 warn("could not get dump device"); 551 return 0; 552 } else if (dev == NODEV) { 553 printf("no dump device set\n"); 554 return 0; 555 } else { 556 name = devname(dev, S_IFBLK); 557 printf("dump device is "); 558 if (name) 559 printf("%s\n", name); 560 else 561 printf("major %llu minor %llu\n", 562 (unsigned long long)major(dev), 563 (unsigned long long)minor(dev)); 564 } 565 return 1; 566 } 567 568 static void 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 710 do_fstab(int add) 711 { 712 struct fstab *fp; 713 char *s; 714 long priority; 715 struct stat st; 716 int isblk; 717 int success = 0; /* set to 1 after a successful operation */ 718 int error = 0; /* set to 1 after an error */ 719 720 #ifdef RESCUEDIR 721 #define PATH_MOUNT RESCUEDIR "/mount_nfs" 722 #define PATH_UMOUNT RESCUEDIR "/umount" 723 #else 724 #define PATH_MOUNT "/sbin/mount_nfs" 725 #define PATH_UMOUNT "/sbin/umount" 726 #endif 727 728 char cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2]; 729 730 #define PRIORITYEQ "priority=" 731 #define NFSMNTPT "nfsmntpt=" 732 while ((fp = getfsent()) != NULL) { 733 char buf[MAXPATHLEN]; 734 char *spec, *fsspec; 735 736 /* 737 * Ignore any entries which are not related to swapping 738 */ 739 if (strcmp(fp->fs_type, "sw") != 0 && 740 strcmp(fp->fs_type, "dp") != 0) 741 continue; 742 743 if (getfsspecname(buf, sizeof(buf), fp->fs_spec) == NULL) { 744 warn("%s", buf); 745 continue; 746 } 747 fsspec = spec = buf; 748 cmd[0] = '\0'; 749 750 if (strcmp(fp->fs_type, "dp") == 0 && add) { 751 set_dumpdev1(spec); 752 continue; 753 } 754 755 /* handle dp as mnt option */ 756 if (strstr(fp->fs_mntops, "dp") && add) 757 set_dumpdev1(spec); 758 759 isblk = 0; 760 761 if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) { 762 s += sizeof(PRIORITYEQ) - 1; 763 priority = atol(s); 764 } else 765 priority = pri; 766 767 if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) { 768 char *t; 769 770 /* 771 * Skip this song and dance if we're only 772 * doing block devices. 773 */ 774 if (tflag != NULL && strcmp(tflag, "blk") == 0) 775 continue; 776 777 t = strpbrk(s, ","); 778 if (t != 0) 779 *t = '\0'; 780 spec = strdup(s + strlen(NFSMNTPT)); 781 if (t != 0) 782 *t = ','; 783 784 if (spec == NULL) 785 errx(1, "Out of memory"); 786 787 if (strlen(spec) == 0) { 788 warnx("empty mountpoint"); 789 free(spec); 790 continue; 791 } 792 if (add) { 793 snprintf(cmd, sizeof(cmd), "%s %s %s", 794 PATH_MOUNT, fsspec, spec); 795 if (system(cmd) != 0) { 796 warnx("%s: mount failed", fsspec); 797 continue; 798 } 799 } else { 800 snprintf(cmd, sizeof(cmd), "%s %s", 801 PATH_UMOUNT, fsspec); 802 } 803 } else { 804 /* 805 * Determine blk-ness. 806 */ 807 if (stat(spec, &st) < 0) { 808 warn("%s", spec); 809 continue; 810 } 811 if (S_ISBLK(st.st_mode)) 812 isblk = 1; 813 } 814 815 /* 816 * Skip this type if we're told to. 817 */ 818 if (tflag != NULL) { 819 if (strcmp(tflag, "blk") == 0 && isblk == 0) 820 continue; 821 if (strcmp(tflag, "noblk") == 0 && isblk == 1) 822 continue; 823 } 824 825 if (add) { 826 if (add_swap(spec, (int)priority)) { 827 success = 1; 828 printf( 829 "%s: adding %s as swap device at priority %d\n", 830 getprogname(), fsspec, (int)priority); 831 } else { 832 error = 1; 833 fprintf(stderr, 834 "%s: failed to add %s as swap device\n", 835 getprogname(), fsspec); 836 } 837 } else { 838 if (delete_swap(spec)) { 839 success = 1; 840 printf( 841 "%s: removing %s as swap device\n", 842 getprogname(), fsspec); 843 } else { 844 error = 1; 845 fprintf(stderr, 846 "%s: failed to remove %s as swap device\n", 847 getprogname(), fsspec); 848 } 849 if (cmd[0]) { 850 if (system(cmd) != 0) { 851 warnx("%s: umount failed", fsspec); 852 error = 1; 853 continue; 854 } 855 } 856 } 857 858 if (spec != fsspec) 859 free(spec); 860 } 861 if (error) 862 exit(1); 863 else if (success) 864 exit(0); 865 else 866 exit(2); /* not really an error, but no swap devices found */ 867 } 868 869 static void 870 usage(void) 871 { 872 const char *progname = getprogname(); 873 874 fprintf(stderr, "usage: %s -A [-f|-o] [-n] [-p priority] " 875 "[-t blk|noblk|auto]\n", progname); 876 fprintf(stderr, " %s -a [-p priority] path\n", progname); 877 fprintf(stderr, " %s -q\n", progname); 878 fprintf(stderr, " %s -c -p priority path\n", progname); 879 fprintf(stderr, " %s -D dumpdev|none\n", progname); 880 fprintf(stderr, " %s -d path\n", progname); 881 fprintf(stderr, " %s -l | -s [-k|-m|-g|-h]\n", progname); 882 fprintf(stderr, " %s -U [-n] [-t blk|noblk|auto]\n", progname); 883 fprintf(stderr, " %s -z\n", progname); 884 exit(1); 885 } 886