1*b638aa94Smillert /* $OpenBSD: swapctl.c,v 1.3 2000/06/30 16:00:09 millert Exp $ */ 2694f38efSweingart /* $NetBSD: swapctl.c,v 1.9 1998/07/26 20:23:15 mycroft Exp $ */ 3694f38efSweingart 4694f38efSweingart /* 5694f38efSweingart * Copyright (c) 1996, 1997 Matthew R. Green 6694f38efSweingart * All rights reserved. 7694f38efSweingart * 8694f38efSweingart * Redistribution and use in source and binary forms, with or without 9694f38efSweingart * modification, are permitted provided that the following conditions 10694f38efSweingart * are met: 11694f38efSweingart * 1. Redistributions of source code must retain the above copyright 12694f38efSweingart * notice, this list of conditions and the following disclaimer. 13694f38efSweingart * 2. Redistributions in binary form must reproduce the above copyright 14694f38efSweingart * notice, this list of conditions and the following disclaimer in the 15694f38efSweingart * documentation and/or other materials provided with the distribution. 16694f38efSweingart * 3. The name of the author may not be used to endorse or promote products 17694f38efSweingart * derived from this software without specific prior written permission. 18694f38efSweingart * 19694f38efSweingart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20694f38efSweingart * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21694f38efSweingart * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22694f38efSweingart * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23694f38efSweingart * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24694f38efSweingart * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25694f38efSweingart * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26694f38efSweingart * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27694f38efSweingart * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28694f38efSweingart * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29694f38efSweingart * SUCH DAMAGE. 30694f38efSweingart */ 31694f38efSweingart 32694f38efSweingart /* 33694f38efSweingart * swapctl command: 34694f38efSweingart * -A add all devices listed as `sw' in /etc/fstab 35694f38efSweingart * -t [blk|noblk] if -A, add either all block device or all non-block 36694f38efSweingart * devices 37694f38efSweingart * -a <dev> add this device 38694f38efSweingart * -d <dev> remove this swap device (not supported yet) 39694f38efSweingart * -l list swap devices 40694f38efSweingart * -s short listing of swap devices 41694f38efSweingart * -k use kilobytes 42694f38efSweingart * -p <pri> use this priority 43694f38efSweingart * -c change priority 44694f38efSweingart * 45694f38efSweingart * or, if invoked as "swapon" (compatibility mode): 46694f38efSweingart * 47694f38efSweingart * -a all devices listed as `sw' in /etc/fstab 48694f38efSweingart * -t same as -t above (feature not present in old 49694f38efSweingart * swapon(8) command) 50694f38efSweingart * <dev> add this device 51694f38efSweingart */ 52694f38efSweingart 53694f38efSweingart #include <sys/param.h> 54694f38efSweingart #include <sys/stat.h> 55694f38efSweingart 56694f38efSweingart #include <sys/swap.h> 57694f38efSweingart 58694f38efSweingart #include <unistd.h> 59694f38efSweingart #include <err.h> 60694f38efSweingart #include <errno.h> 61694f38efSweingart #include <stdio.h> 62694f38efSweingart #include <stdlib.h> 63694f38efSweingart #include <string.h> 64694f38efSweingart #include <fstab.h> 65694f38efSweingart 66694f38efSweingart #include "swapctl.h" 67694f38efSweingart 68694f38efSweingart int command; 69694f38efSweingart 70694f38efSweingart /* 71694f38efSweingart * Commands for swapctl(8). These are mutually exclusive. 72694f38efSweingart */ 73694f38efSweingart #define CMD_A 0x01 /* process /etc/fstab */ 74694f38efSweingart #define CMD_a 0x02 /* add a swap file/device */ 75694f38efSweingart #define CMD_c 0x04 /* change priority of a swap file/device */ 76694f38efSweingart #define CMD_d 0x08 /* delete a swap file/device */ 77694f38efSweingart #define CMD_l 0x10 /* list swap files/devices */ 78694f38efSweingart #define CMD_s 0x20 /* summary of swap files/devices */ 79694f38efSweingart 80694f38efSweingart #define SET_COMMAND(cmd) \ 81694f38efSweingart do { \ 82694f38efSweingart if (command) \ 83694f38efSweingart usage(); \ 84694f38efSweingart command = (cmd); \ 85694f38efSweingart } while (0) 86694f38efSweingart 87694f38efSweingart /* 88694f38efSweingart * Commands that require a "path" argument at the end of the command 89694f38efSweingart * line, and the ones which require that none exist. 90694f38efSweingart */ 91694f38efSweingart #define REQUIRE_PATH (CMD_a | CMD_c | CMD_d) 92694f38efSweingart #define REQUIRE_NOPATH (CMD_A | CMD_l | CMD_s) 93694f38efSweingart 94694f38efSweingart /* 95694f38efSweingart * Option flags, and the commands with which they are valid. 96694f38efSweingart */ 97694f38efSweingart int kflag; /* display in 1K blocks */ 98694f38efSweingart #define KFLAG_CMDS (CMD_l | CMD_s) 99694f38efSweingart 100694f38efSweingart int pflag; /* priority was specified */ 101694f38efSweingart #define PFLAG_CMDS (CMD_A | CMD_a | CMD_c) 102694f38efSweingart 103694f38efSweingart char *tflag; /* swap device type (blk or noblk) */ 104694f38efSweingart #define TFLAG_CMDS (CMD_A) 105694f38efSweingart 106694f38efSweingart int pri; /* uses 0 as default pri */ 107694f38efSweingart 108694f38efSweingart static void change_priority __P((char *)); 109694f38efSweingart static void add_swap __P((char *)); 110694f38efSweingart static void del_swap __P((char *)); 111694f38efSweingart int main __P((int, char *[])); 112694f38efSweingart static void do_fstab __P((void)); 113694f38efSweingart static void usage __P((void)); 114694f38efSweingart static void swapon_command __P((int, char **)); 115694f38efSweingart #if 0 116694f38efSweingart static void swapoff_command __P((int, char **)); 117694f38efSweingart #endif 118694f38efSweingart 119694f38efSweingart extern char *__progname; /* from crt0.o */ 120694f38efSweingart 121694f38efSweingart int 122694f38efSweingart main(argc, argv) 123694f38efSweingart int argc; 124694f38efSweingart char *argv[]; 125694f38efSweingart { 126694f38efSweingart int c; 127694f38efSweingart 128694f38efSweingart if (strcmp(__progname, "swapon") == 0) { 129694f38efSweingart swapon_command(argc, argv); 130694f38efSweingart /* NOTREACHED */ 131694f38efSweingart } 132694f38efSweingart 133694f38efSweingart #if 0 134694f38efSweingart if (strcmp(__progname, "swapoff") == 0) { 135694f38efSweingart swapoff_command(argc, argv); 136694f38efSweingart /* NOTREACHED */ 137694f38efSweingart } 138694f38efSweingart #endif 139694f38efSweingart 140694f38efSweingart while ((c = getopt(argc, argv, "Aacdlkp:st:")) != -1) { 141694f38efSweingart switch (c) { 142694f38efSweingart case 'A': 143694f38efSweingart SET_COMMAND(CMD_A); 144694f38efSweingart break; 145694f38efSweingart 146694f38efSweingart case 'a': 147694f38efSweingart SET_COMMAND(CMD_a); 148694f38efSweingart break; 149694f38efSweingart 150694f38efSweingart case 'c': 151694f38efSweingart SET_COMMAND(CMD_c); 152694f38efSweingart break; 153694f38efSweingart 154694f38efSweingart case 'd': 155694f38efSweingart SET_COMMAND(CMD_d); 156694f38efSweingart break; 157694f38efSweingart 158694f38efSweingart case 'l': 159694f38efSweingart SET_COMMAND(CMD_l); 160694f38efSweingart break; 161694f38efSweingart 162694f38efSweingart case 'k': 163694f38efSweingart kflag = 1; 164694f38efSweingart break; 165694f38efSweingart 166694f38efSweingart case 'p': 167694f38efSweingart pflag = 1; 168694f38efSweingart /* XXX strtol() */ 169694f38efSweingart pri = atoi(optarg); 170694f38efSweingart break; 171694f38efSweingart 172694f38efSweingart case 's': 173694f38efSweingart SET_COMMAND(CMD_s); 174694f38efSweingart break; 175694f38efSweingart 176694f38efSweingart case 't': 177694f38efSweingart if (tflag != NULL) 178694f38efSweingart usage(); 179694f38efSweingart tflag = optarg; 180694f38efSweingart break; 181694f38efSweingart 182694f38efSweingart default: 183694f38efSweingart usage(); 184694f38efSweingart /* NOTREACHED */ 185694f38efSweingart } 186694f38efSweingart } 187694f38efSweingart 188694f38efSweingart /* Did the user specify a command? */ 189694f38efSweingart if (command == 0) 190694f38efSweingart usage(); 191694f38efSweingart 192694f38efSweingart argv += optind; 193694f38efSweingart argc -= optind; 194694f38efSweingart 195694f38efSweingart switch (argc) { 196694f38efSweingart case 0: 197694f38efSweingart if (command & REQUIRE_PATH) 198694f38efSweingart usage(); 199694f38efSweingart break; 200694f38efSweingart 201694f38efSweingart case 1: 202694f38efSweingart if (command & REQUIRE_NOPATH) 203694f38efSweingart usage(); 204694f38efSweingart break; 205694f38efSweingart 206694f38efSweingart default: 207694f38efSweingart usage(); 208694f38efSweingart } 209694f38efSweingart 210694f38efSweingart /* To change priority, you have to specify one. */ 211694f38efSweingart if ((command == CMD_c) && pflag == 0) 212694f38efSweingart usage(); 213694f38efSweingart 214694f38efSweingart /* Sanity-check -t */ 215694f38efSweingart if (tflag != NULL) { 216694f38efSweingart if (command != CMD_A) 217694f38efSweingart usage(); 218694f38efSweingart if (strcmp(tflag, "blk") != 0 && 219694f38efSweingart strcmp(tflag, "noblk") != 0) 220694f38efSweingart usage(); 221694f38efSweingart } 222694f38efSweingart 223694f38efSweingart /* Dispatch the command. */ 224694f38efSweingart switch (command) { 225694f38efSweingart case CMD_l: 226694f38efSweingart list_swap(pri, kflag, pflag, 0, 1); 227694f38efSweingart break; 228694f38efSweingart 229694f38efSweingart case CMD_s: 230694f38efSweingart list_swap(pri, kflag, pflag, 0, 0); 231694f38efSweingart break; 232694f38efSweingart 233694f38efSweingart case CMD_c: 234694f38efSweingart change_priority(argv[0]); 235694f38efSweingart break; 236694f38efSweingart 237694f38efSweingart case CMD_a: 238694f38efSweingart add_swap(argv[0]); 239694f38efSweingart break; 240694f38efSweingart 241694f38efSweingart case CMD_d: 242694f38efSweingart del_swap(argv[0]); 243694f38efSweingart break; 244694f38efSweingart 245694f38efSweingart case CMD_A: 246694f38efSweingart do_fstab(); 247694f38efSweingart break; 248694f38efSweingart } 249694f38efSweingart 250694f38efSweingart exit(0); 251694f38efSweingart } 252694f38efSweingart 253694f38efSweingart /* 254694f38efSweingart * swapon_command: emulate the old swapon(8) program. 255694f38efSweingart */ 256694f38efSweingart void 257694f38efSweingart swapon_command(argc, argv) 258694f38efSweingart int argc; 259694f38efSweingart char **argv; 260694f38efSweingart { 261694f38efSweingart int ch, fiztab = 0; 262694f38efSweingart 263694f38efSweingart while ((ch = getopt(argc, argv, "at:")) != -1) { 264694f38efSweingart switch (ch) { 265694f38efSweingart case 'a': 266694f38efSweingart fiztab = 1; 267694f38efSweingart break; 268694f38efSweingart case 't': 269694f38efSweingart if (tflag != NULL) 270694f38efSweingart usage(); 271694f38efSweingart tflag = optarg; 272694f38efSweingart break; 273694f38efSweingart default: 274694f38efSweingart goto swapon_usage; 275694f38efSweingart } 276694f38efSweingart } 277694f38efSweingart argc -= optind; 278694f38efSweingart argv += optind; 279694f38efSweingart 280694f38efSweingart if (fiztab) { 281694f38efSweingart if (argc) 282694f38efSweingart goto swapon_usage; 283694f38efSweingart /* Sanity-check -t */ 284694f38efSweingart if (tflag != NULL) { 285694f38efSweingart if (strcmp(tflag, "blk") != 0 && 286694f38efSweingart strcmp(tflag, "noblk") != 0) 287694f38efSweingart usage(); 288694f38efSweingart } 289694f38efSweingart do_fstab(); 290694f38efSweingart exit(0); 291694f38efSweingart } else if (argc == 0 || tflag != NULL) 292694f38efSweingart goto swapon_usage; 293694f38efSweingart 294694f38efSweingart while (argc) { 295694f38efSweingart add_swap(argv[0]); 296694f38efSweingart argc--; 297694f38efSweingart argv++; 298694f38efSweingart } 299694f38efSweingart exit(0); 300694f38efSweingart /* NOTREACHED */ 301694f38efSweingart 302694f38efSweingart swapon_usage: 303694f38efSweingart fprintf(stderr, "usage: %s -a [-t blk|noblk]\n", __progname); 304694f38efSweingart fprintf(stderr, " %s <path> ...\n", __progname); 305694f38efSweingart exit(1); 306694f38efSweingart } 307694f38efSweingart 308694f38efSweingart /* 309694f38efSweingart * change_priority: change the priority of a swap device. 310694f38efSweingart */ 311694f38efSweingart void 312694f38efSweingart change_priority(path) 313694f38efSweingart char *path; 314694f38efSweingart { 315694f38efSweingart 316694f38efSweingart if (swapctl(SWAP_CTL, path, pri) < 0) 317694f38efSweingart warn("%s", path); 318694f38efSweingart } 319694f38efSweingart 320694f38efSweingart /* 321694f38efSweingart * add_swap: add the pathname to the list of swap devices. 322694f38efSweingart */ 323694f38efSweingart void 324694f38efSweingart add_swap(path) 325694f38efSweingart char *path; 326694f38efSweingart { 327694f38efSweingart 328694f38efSweingart if (swapctl(SWAP_ON, path, pri) < 0) 329694f38efSweingart err(1, "%s", path); 330694f38efSweingart } 331694f38efSweingart 332694f38efSweingart /* 333694f38efSweingart * del_swap: remove the pathname to the list of swap devices. 334694f38efSweingart */ 335694f38efSweingart void 336694f38efSweingart del_swap(path) 337694f38efSweingart char *path; 338694f38efSweingart { 339694f38efSweingart 340694f38efSweingart if (swapctl(SWAP_OFF, path, pri) < 0) 341694f38efSweingart err(1, "%s", path); 342694f38efSweingart } 343694f38efSweingart 344694f38efSweingart void 345694f38efSweingart do_fstab() 346694f38efSweingart { 347694f38efSweingart struct fstab *fp; 348694f38efSweingart char *s; 349694f38efSweingart long priority; 350694f38efSweingart struct stat st; 351694f38efSweingart int isblk; 352694f38efSweingart int gotone = 0; 353694f38efSweingart 354694f38efSweingart #define PRIORITYEQ "priority=" 355694f38efSweingart #define NFSMNTPT "nfsmntpt=" 356694f38efSweingart #define PATH_MOUNT "/sbin/mount_nfs" 357694f38efSweingart while ((fp = getfsent()) != NULL) { 358694f38efSweingart const char *spec; 359694f38efSweingart 360694f38efSweingart if (strcmp(fp->fs_type, "sw") != 0) 361694f38efSweingart continue; 362694f38efSweingart 363694f38efSweingart spec = fp->fs_spec; 364694f38efSweingart isblk = 0; 365694f38efSweingart 366694f38efSweingart if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) { 367694f38efSweingart s += sizeof(PRIORITYEQ) - 1; 368694f38efSweingart priority = atol(s); 369694f38efSweingart } else 370694f38efSweingart priority = pri; 371694f38efSweingart 372694f38efSweingart if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) { 373694f38efSweingart char *t, cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2]; 374694f38efSweingart 375694f38efSweingart /* 376694f38efSweingart * Skip this song and dance if we're only 377694f38efSweingart * doing block devices. 378694f38efSweingart */ 379694f38efSweingart if (tflag != NULL && 380694f38efSweingart strcmp(tflag, "blk") == 0) 381694f38efSweingart continue; 382694f38efSweingart 383694f38efSweingart t = strpbrk(s, ","); 384694f38efSweingart if (t != 0) 385694f38efSweingart *t = '\0'; 386694f38efSweingart spec = strdup(s + strlen(NFSMNTPT)); 387694f38efSweingart if (t != 0) 388694f38efSweingart *t = ','; 389694f38efSweingart 390694f38efSweingart if (spec == NULL) 391694f38efSweingart errx(1, "Out of memory"); 392694f38efSweingart 393694f38efSweingart if (strlen(spec) == 0) { 394694f38efSweingart warnx("empty mountpoint"); 395694f38efSweingart free((char *)spec); 396694f38efSweingart continue; 397694f38efSweingart } 398694f38efSweingart snprintf(cmd, sizeof(cmd), "%s %s %s", 399694f38efSweingart PATH_MOUNT, fp->fs_spec, spec); 400694f38efSweingart if (system(cmd) != 0) { 401694f38efSweingart warnx("%s: mount failed", fp->fs_spec); 402694f38efSweingart continue; 403694f38efSweingart } 404694f38efSweingart } else { 405694f38efSweingart /* 406694f38efSweingart * Determine blk-ness. 407694f38efSweingart */ 408694f38efSweingart if (stat(spec, &st) < 0) { 409*b638aa94Smillert warn("%s", spec); 410694f38efSweingart continue; 411694f38efSweingart } 412694f38efSweingart if (S_ISBLK(st.st_mode)) 413694f38efSweingart isblk = 1; 414694f38efSweingart } 415694f38efSweingart 416694f38efSweingart /* 417694f38efSweingart * Skip this type if we're told to. 418694f38efSweingart */ 419694f38efSweingart if (tflag != NULL) { 420694f38efSweingart if (strcmp(tflag, "blk") == 0 && isblk == 0) 421694f38efSweingart continue; 422694f38efSweingart if (strcmp(tflag, "noblk") == 0 && isblk == 1) 423694f38efSweingart continue; 424694f38efSweingart } 425694f38efSweingart 426694f38efSweingart if (swapctl(SWAP_ON, spec, (int)priority) < 0) 427694f38efSweingart warn("%s", spec); 428694f38efSweingart else { 429694f38efSweingart gotone = 1; 430694f38efSweingart printf("%s: adding %s as swap device at priority %d\n", 431694f38efSweingart __progname, fp->fs_spec, (int)priority); 432694f38efSweingart } 433694f38efSweingart 434694f38efSweingart if (spec != fp->fs_spec) 435694f38efSweingart free((char *)spec); 436694f38efSweingart } 437694f38efSweingart if (gotone == 0) 438694f38efSweingart exit(1); 439694f38efSweingart } 440694f38efSweingart 441694f38efSweingart void 442694f38efSweingart usage() 443694f38efSweingart { 444694f38efSweingart 445694f38efSweingart fprintf(stderr, "usage: %s -A [-p priority] [-t blk|noblk]\n", 446694f38efSweingart __progname); 447694f38efSweingart fprintf(stderr, " %s -a [-p priority] path\n", __progname); 448694f38efSweingart fprintf(stderr, " %s -c -p priority path\n", __progname); 449694f38efSweingart fprintf(stderr, " %s -d path\n", __progname); 450694f38efSweingart fprintf(stderr, " %s -l | -s [-k]\n", __progname); 451694f38efSweingart exit(1); 452694f38efSweingart } 453