1 /* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #if 0 31 #ifndef lint 32 static const char copyright[] = 33 "@(#) Copyright (c) 1980, 1993\n\ 34 The Regents of the University of California. All rights reserved.\n"; 35 #endif /* not lint */ 36 37 #ifndef lint 38 static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93"; 39 #endif /* not lint */ 40 #endif 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/stat.h> 45 #include <sys/param.h> 46 #include <sys/sysctl.h> 47 #include <vm/vm_param.h> 48 49 #include <err.h> 50 #include <errno.h> 51 #include <fstab.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 #include <fcntl.h> 57 #include <libutil.h> 58 59 static void usage(void); 60 static int swap_on_off(char *name, int ignoreebusy); 61 static void swaplist(int, int, int); 62 63 enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 64 65 int 66 main(int argc, char **argv) 67 { 68 struct fstab *fsp; 69 char *ptr; 70 int stat; 71 int ch, doall; 72 int sflag = 0, lflag = 0, hflag = 0; 73 74 if ((ptr = strrchr(argv[0], '/')) == NULL) 75 ptr = argv[0]; 76 if (strstr(ptr, "swapon")) 77 which_prog = SWAPON; 78 else if (strstr(ptr, "swapoff")) 79 which_prog = SWAPOFF; 80 orig_prog = which_prog; 81 82 doall = 0; 83 while ((ch = getopt(argc, argv, "AadghklmsU")) != -1) { 84 switch(ch) { 85 case 'A': 86 if (which_prog == SWAPCTL) { 87 doall = 1; 88 which_prog = SWAPON; 89 } else { 90 usage(); 91 } 92 break; 93 case 'a': 94 if (which_prog == SWAPON || which_prog == SWAPOFF) 95 doall = 1; 96 else 97 which_prog = SWAPON; 98 break; 99 case 'd': 100 if (which_prog == SWAPCTL) 101 which_prog = SWAPOFF; 102 else 103 usage(); 104 break; 105 case 'g': 106 hflag = 'G'; 107 break; 108 case 'h': 109 hflag = 'H'; 110 break; 111 case 'k': 112 hflag = 'K'; 113 break; 114 case 'l': 115 lflag = 1; 116 break; 117 case 'm': 118 hflag = 'M'; 119 break; 120 case 's': 121 sflag = 1; 122 break; 123 case 'U': 124 if (which_prog == SWAPCTL) { 125 doall = 1; 126 which_prog = SWAPOFF; 127 } else { 128 usage(); 129 } 130 break; 131 case '?': 132 default: 133 usage(); 134 } 135 } 136 argv += optind; 137 138 stat = 0; 139 if (which_prog == SWAPON || which_prog == SWAPOFF) { 140 if (doall) { 141 while ((fsp = getfsent()) != NULL) { 142 if (strcmp(fsp->fs_type, FSTAB_SW)) 143 continue; 144 if (strstr(fsp->fs_mntops, "noauto")) 145 continue; 146 if (swap_on_off(fsp->fs_spec, 1)) { 147 stat = 1; 148 } else { 149 printf("%s: %sing %s as swap device\n", 150 getprogname(), which_prog == SWAPOFF ? "remov" : "add", 151 fsp->fs_spec); 152 } 153 } 154 } 155 else if (!*argv) 156 usage(); 157 for (; *argv; ++argv) { 158 if (swap_on_off(*argv, 0)) { 159 stat = 1; 160 } else if (orig_prog == SWAPCTL) { 161 printf("%s: %sing %s as swap device\n", 162 getprogname(), which_prog == SWAPOFF ? "remov" : "add", 163 *argv); 164 } 165 } 166 } else { 167 if (lflag || sflag) 168 swaplist(lflag, sflag, hflag); 169 else 170 usage(); 171 } 172 exit(stat); 173 } 174 175 static int 176 swap_on_off(char *name, int doingall) 177 { 178 if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) { 179 switch (errno) { 180 case EBUSY: 181 if (!doingall) 182 warnx("%s: device already in use", name); 183 break; 184 case EINVAL: 185 if (which_prog == SWAPON) 186 warnx("%s: NSWAPDEV limit reached", name); 187 else if (!doingall) 188 warn("%s", name); 189 break; 190 default: 191 warn("%s", name); 192 break; 193 } 194 return(1); 195 } 196 return(0); 197 } 198 199 static void 200 usage(void) 201 { 202 fprintf(stderr, "usage: %s ", getprogname()); 203 switch(orig_prog) { 204 case SWAPON: 205 case SWAPOFF: 206 fprintf(stderr, "-a | file ...\n"); 207 break; 208 case SWAPCTL: 209 fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 210 break; 211 } 212 exit(1); 213 } 214 215 static void 216 sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 217 long blocksize) 218 { 219 220 if (hflag == 'H') { 221 char tmp[16]; 222 223 humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 224 HN_B | HN_NOSPACE | HN_DECIMAL); 225 snprintf(buf, bufsize, "%*s", hlen, tmp); 226 } else { 227 snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 228 } 229 } 230 231 static void 232 swaplist(int lflag, int sflag, int hflag) 233 { 234 size_t mibsize, size; 235 struct xswdev xsw; 236 int hlen, mib[16], n, pagesize; 237 long blocksize; 238 long long total = 0; 239 long long used = 0; 240 long long tmp_total; 241 long long tmp_used; 242 char buf[32]; 243 244 pagesize = getpagesize(); 245 switch(hflag) { 246 case 'G': 247 blocksize = 1024 * 1024 * 1024; 248 strlcpy(buf, "1GB-blocks", sizeof(buf)); 249 hlen = 10; 250 break; 251 case 'H': 252 blocksize = -1; 253 strlcpy(buf, "Bytes", sizeof(buf)); 254 hlen = 10; 255 break; 256 case 'K': 257 blocksize = 1024; 258 strlcpy(buf, "1kB-blocks", sizeof(buf)); 259 hlen = 10; 260 break; 261 case 'M': 262 blocksize = 1024 * 1024; 263 strlcpy(buf, "1MB-blocks", sizeof(buf)); 264 hlen = 10; 265 break; 266 default: 267 getbsize(&hlen, &blocksize); 268 snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 269 break; 270 } 271 272 mibsize = sizeof mib / sizeof mib[0]; 273 if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 274 err(1, "sysctlnametomib()"); 275 276 if (lflag) { 277 printf("%-13s %*s %*s\n", 278 "Device:", 279 hlen, buf, 280 hlen, "Used:"); 281 } 282 283 for (n = 0; ; ++n) { 284 mib[mibsize] = n; 285 size = sizeof xsw; 286 if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 287 break; 288 if (xsw.xsw_version != XSWDEV_VERSION) 289 errx(1, "xswdev version mismatch"); 290 291 tmp_total = (long long)xsw.xsw_nblks * pagesize; 292 tmp_used = (long long)xsw.xsw_used * pagesize; 293 total += tmp_total; 294 used += tmp_used; 295 if (lflag) { 296 sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 297 blocksize); 298 printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 299 buf); 300 sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 301 blocksize); 302 printf("%s\n", buf); 303 } 304 } 305 if (errno != ENOENT) 306 err(1, "sysctl()"); 307 308 if (sflag) { 309 sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 310 printf("Total: %s ", buf); 311 sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 312 printf("%s\n", buf); 313 } 314 } 315 316