179ba2f31SHiroki Sato /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 48fae3551SRodney W. Grimes * Copyright (c) 1980, 1993 58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 68fae3551SRodney W. Grimes * 78fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 88fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 98fae3551SRodney W. Grimes * are met: 108fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 128fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 138fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 148fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 168fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 178fae3551SRodney W. Grimes * without specific prior written permission. 188fae3551SRodney W. Grimes * 198fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 208fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 218fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 228fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 238fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 248fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 258fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 268fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 278fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 288fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 298fae3551SRodney W. Grimes * SUCH DAMAGE. 308fae3551SRodney W. Grimes */ 318fae3551SRodney W. Grimes 32a420c811SMatthew Dillon #include <sys/param.h> 339035b225SDoug Moore #include <sys/disk.h> 34504f5e29SDoug Moore #include <sys/disklabel.h> 35268a55bcSHiroki Sato #include <sys/mdioctl.h> 36268a55bcSHiroki Sato #include <sys/stat.h> 37a420c811SMatthew Dillon #include <sys/sysctl.h> 38268a55bcSHiroki Sato #include <sys/wait.h> 396004362eSDavid Schultz #include <vm/vm_param.h> 401aa249c9SKonstantin Belousov #include <vm/swap_pager.h> 41a420c811SMatthew Dillon 426da7f378SPhilippe Charnier #include <err.h> 43e798a806SPhilippe Charnier #include <errno.h> 44268a55bcSHiroki Sato #include <fcntl.h> 45268a55bcSHiroki Sato #include <fnmatch.h> 46e798a806SPhilippe Charnier #include <fstab.h> 47268a55bcSHiroki Sato #include <libgen.h> 48268a55bcSHiroki Sato #include <libutil.h> 49268a55bcSHiroki Sato #include <limits.h> 50268a55bcSHiroki Sato #include <paths.h> 51268a55bcSHiroki Sato #include <stdarg.h> 52e798a806SPhilippe Charnier #include <stdio.h> 53cafefe8cSDima Dorfman #include <stdlib.h> 54e798a806SPhilippe Charnier #include <string.h> 55e798a806SPhilippe Charnier #include <unistd.h> 568fae3551SRodney W. Grimes 5765f3be91SAlfonso Gregory static void usage(void) __dead2; 588f8de1e1SXin LI static const char *swap_on_off(const char *, int, char *); 598f8de1e1SXin LI static const char *swap_on_off_geli(const char *, char *, int); 608f8de1e1SXin LI static const char *swap_on_off_md(const char *, char *, int); 618f8de1e1SXin LI static const char *swap_on_off_sfile(const char *, int); 62a420c811SMatthew Dillon static void swaplist(int, int, int); 63268a55bcSHiroki Sato static int run_cmd(int *, const char *, ...) __printflike(2, 3); 64a420c811SMatthew Dillon 651efe3c6bSEd Schouten static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 6638994f93SPoul-Henning Kamp 671aa249c9SKonstantin Belousov static int Eflag, fflag, qflag; 68268a55bcSHiroki Sato 6938994f93SPoul-Henning Kamp int 7038994f93SPoul-Henning Kamp main(int argc, char **argv) 718fae3551SRodney W. Grimes { 723d438ad6SDavid E. O'Brien struct fstab *fsp; 73268a55bcSHiroki Sato const char *swfile; 74a420c811SMatthew Dillon char *ptr; 7579ba2f31SHiroki Sato int ret, ch, doall; 7679ba2f31SHiroki Sato int sflag, lflag, late, hflag; 77633d2bc5SMaxim Sobolev const char *etc_fstab; 7892da00bbSMatthew Dillon 7979ba2f31SHiroki Sato sflag = lflag = late = hflag = 0; 80a420c811SMatthew Dillon if ((ptr = strrchr(argv[0], '/')) == NULL) 81a420c811SMatthew Dillon ptr = argv[0]; 8279ba2f31SHiroki Sato if (strstr(ptr, "swapon") != NULL) 83a420c811SMatthew Dillon which_prog = SWAPON; 8479ba2f31SHiroki Sato else if (strstr(ptr, "swapoff") != NULL) 85a420c811SMatthew Dillon which_prog = SWAPOFF; 86a420c811SMatthew Dillon orig_prog = which_prog; 878fae3551SRodney W. Grimes 888fae3551SRodney W. Grimes doall = 0; 89633d2bc5SMaxim Sobolev etc_fstab = NULL; 901aa249c9SKonstantin Belousov while ((ch = getopt(argc, argv, "AadEfghklLmqsUF:")) != -1) { 91a420c811SMatthew Dillon switch(ch) { 92a420c811SMatthew Dillon case 'A': 93a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 948fae3551SRodney W. Grimes doall = 1; 95a420c811SMatthew Dillon which_prog = SWAPON; 9679ba2f31SHiroki Sato } else 97a420c811SMatthew Dillon usage(); 98a420c811SMatthew Dillon break; 99a420c811SMatthew Dillon case 'a': 100a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) 101a420c811SMatthew Dillon doall = 1; 102a420c811SMatthew Dillon else 103a420c811SMatthew Dillon which_prog = SWAPON; 104a420c811SMatthew Dillon break; 105a420c811SMatthew Dillon case 'd': 106a420c811SMatthew Dillon if (which_prog == SWAPCTL) 107a420c811SMatthew Dillon which_prog = SWAPOFF; 108a420c811SMatthew Dillon else 109a420c811SMatthew Dillon usage(); 110a420c811SMatthew Dillon break; 111a616b253SDoug Moore case 'E': 112a616b253SDoug Moore if (which_prog == SWAPON) 113a616b253SDoug Moore Eflag = 2; 114a616b253SDoug Moore else 115a616b253SDoug Moore usage(); 116a616b253SDoug Moore break; 1171aa249c9SKonstantin Belousov case 'f': 1181aa249c9SKonstantin Belousov if (which_prog == SWAPOFF) 1191aa249c9SKonstantin Belousov fflag = 1; 1201aa249c9SKonstantin Belousov else 1211aa249c9SKonstantin Belousov usage(); 1221aa249c9SKonstantin Belousov break; 1232e64768cSPawel Jakub Dawidek case 'g': 1242e64768cSPawel Jakub Dawidek hflag = 'G'; 1252e64768cSPawel Jakub Dawidek break; 1262e64768cSPawel Jakub Dawidek case 'h': 1272e64768cSPawel Jakub Dawidek hflag = 'H'; 1282e64768cSPawel Jakub Dawidek break; 1292e64768cSPawel Jakub Dawidek case 'k': 1302e64768cSPawel Jakub Dawidek hflag = 'K'; 131a420c811SMatthew Dillon break; 132a420c811SMatthew Dillon case 'l': 133a420c811SMatthew Dillon lflag = 1; 134a420c811SMatthew Dillon break; 135268a55bcSHiroki Sato case 'L': 136268a55bcSHiroki Sato late = 1; 137268a55bcSHiroki Sato break; 1382e64768cSPawel Jakub Dawidek case 'm': 139a420c811SMatthew Dillon hflag = 'M'; 140a420c811SMatthew Dillon break; 14145a5dc93SMike Makonnen case 'q': 14245a5dc93SMike Makonnen if (which_prog == SWAPON || which_prog == SWAPOFF) 14345a5dc93SMike Makonnen qflag = 1; 14445a5dc93SMike Makonnen break; 1452e64768cSPawel Jakub Dawidek case 's': 1462e64768cSPawel Jakub Dawidek sflag = 1; 147a420c811SMatthew Dillon break; 148a420c811SMatthew Dillon case 'U': 149a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 150a420c811SMatthew Dillon doall = 1; 151a420c811SMatthew Dillon which_prog = SWAPOFF; 15279ba2f31SHiroki Sato } else 153a420c811SMatthew Dillon usage(); 1548fae3551SRodney W. Grimes break; 155633d2bc5SMaxim Sobolev case 'F': 156633d2bc5SMaxim Sobolev etc_fstab = optarg; 157633d2bc5SMaxim Sobolev break; 1588fae3551SRodney W. Grimes case '?': 1598fae3551SRodney W. Grimes default: 160a420c811SMatthew Dillon usage(); 161a420c811SMatthew Dillon } 1628fae3551SRodney W. Grimes } 1638fae3551SRodney W. Grimes argv += optind; 1648fae3551SRodney W. Grimes 165ce458f42SEd Schouten ret = 0; 166268a55bcSHiroki Sato swfile = NULL; 167633d2bc5SMaxim Sobolev if (etc_fstab != NULL) 168633d2bc5SMaxim Sobolev setfstab(etc_fstab); 169a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) { 170a420c811SMatthew Dillon if (doall) { 17138994f93SPoul-Henning Kamp while ((fsp = getfsent()) != NULL) { 1724139627dSHiroki Sato if (strcmp(fsp->fs_type, FSTAB_SW) != 0) 1738fae3551SRodney W. Grimes continue; 1744139627dSHiroki Sato if (strstr(fsp->fs_mntops, "noauto") != NULL) 1757fc4a454SJordan K. Hubbard continue; 176268a55bcSHiroki Sato if (which_prog != SWAPOFF && 1771482f982SHiroki Sato strstr(fsp->fs_mntops, "late") && 1784139627dSHiroki Sato late == 0) 179268a55bcSHiroki Sato continue; 1807627b330SJilles Tjoelker if (which_prog == SWAPOFF && 1817627b330SJilles Tjoelker strstr(fsp->fs_mntops, "late") == NULL && 1827627b330SJilles Tjoelker late != 0) 1837627b330SJilles Tjoelker continue; 184a616b253SDoug Moore Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL); 185268a55bcSHiroki Sato swfile = swap_on_off(fsp->fs_spec, 1, 186268a55bcSHiroki Sato fsp->fs_mntops); 187a616b253SDoug Moore Eflag &= ~1; 188268a55bcSHiroki Sato if (swfile == NULL) { 189ce458f42SEd Schouten ret = 1; 190268a55bcSHiroki Sato continue; 191268a55bcSHiroki Sato } 19279ba2f31SHiroki Sato if (qflag == 0) { 19392da00bbSMatthew Dillon printf("%s: %sing %s as swap device\n", 19445a5dc93SMike Makonnen getprogname(), 195268a55bcSHiroki Sato (which_prog == SWAPOFF) ? 196268a55bcSHiroki Sato "remov" : "add", swfile); 197a420c811SMatthew Dillon } 198a420c811SMatthew Dillon } 19979ba2f31SHiroki Sato } else if (*argv == NULL) 200a420c811SMatthew Dillon usage(); 201a420c811SMatthew Dillon for (; *argv; ++argv) { 202268a55bcSHiroki Sato swfile = swap_on_off(*argv, 0, NULL); 203268a55bcSHiroki Sato if (swfile == NULL) { 204ce458f42SEd Schouten ret = 1; 205268a55bcSHiroki Sato continue; 206268a55bcSHiroki Sato } 207268a55bcSHiroki Sato if (orig_prog == SWAPCTL) { 208a420c811SMatthew Dillon printf("%s: %sing %s as swap device\n", 209268a55bcSHiroki Sato getprogname(), 210268a55bcSHiroki Sato (which_prog == SWAPOFF) ? "remov" : "add", 211268a55bcSHiroki Sato swfile); 212a420c811SMatthew Dillon } 213a420c811SMatthew Dillon } 214a420c811SMatthew Dillon } else { 215a420c811SMatthew Dillon if (lflag || sflag) 216a420c811SMatthew Dillon swaplist(lflag, sflag, hflag); 217a420c811SMatthew Dillon else 218a420c811SMatthew Dillon usage(); 219a420c811SMatthew Dillon } 220ce458f42SEd Schouten exit(ret); 2218fae3551SRodney W. Grimes } 2228fae3551SRodney W. Grimes 223268a55bcSHiroki Sato static const char * 2248f8de1e1SXin LI swap_on_off(const char *name, int doingall, char *mntops) 2258fae3551SRodney W. Grimes { 226e47c947eSEd Schouten char *base, *basebuf; 227268a55bcSHiroki Sato 228268a55bcSHiroki Sato /* Swap on vnode-backed md(4) device. */ 229268a55bcSHiroki Sato if (mntops != NULL && 2308f8de1e1SXin LI (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || 2318f8de1e1SXin LI fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || 232268a55bcSHiroki Sato strncmp(_PATH_DEV MD_NAME, name, 233268a55bcSHiroki Sato sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || 234268a55bcSHiroki Sato strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) 235268a55bcSHiroki Sato return (swap_on_off_md(name, mntops, doingall)); 236268a55bcSHiroki Sato 237e47c947eSEd Schouten basebuf = strdup(name); 238e47c947eSEd Schouten base = basename(basebuf); 2398f8de1e1SXin LI 240268a55bcSHiroki Sato /* Swap on encrypted device by GEOM_ELI. */ 241e47c947eSEd Schouten if (fnmatch("*.eli", base, 0) == 0) { 242e47c947eSEd Schouten free(basebuf); 243268a55bcSHiroki Sato return (swap_on_off_geli(name, mntops, doingall)); 244e47c947eSEd Schouten } 245268a55bcSHiroki Sato 246cf04a777SRicardo Branco /* Swap on special file. */ 247*feabaf8dSWarner Losh free(basebuf); 248268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 249268a55bcSHiroki Sato } 250268a55bcSHiroki Sato 2518f8de1e1SXin LI /* Strip off .bde or .eli suffix from swap device name */ 2528f8de1e1SXin LI static char * 2538f8de1e1SXin LI swap_basename(const char *name) 254268a55bcSHiroki Sato { 255cb754f61SHiroki Sato char *dname, *p; 256268a55bcSHiroki Sato 257cb754f61SHiroki Sato dname = strdup(name); 258cb754f61SHiroki Sato p = strrchr(dname, '.'); 2598f8de1e1SXin LI /* assert(p != NULL); */ 260268a55bcSHiroki Sato *p = '\0'; 261268a55bcSHiroki Sato 2628f8de1e1SXin LI return (dname); 2638f8de1e1SXin LI } 2648f8de1e1SXin LI 2650d8a14f9SXin LI /* Build geli(8) arguments from mntops */ 2668f8de1e1SXin LI static char * 2678f8de1e1SXin LI swap_on_geli_args(const char *mntops) 268268a55bcSHiroki Sato { 2698f8de1e1SXin LI const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; 270445bda3fSPawel Jakub Dawidek const char *aflag, *eflag, *lflag, *Tflag, *sflag; 27179ba2f31SHiroki Sato char *p, *args, *token, *string, *ops; 27224cd0f85SEnji Cooper int pagesize; 2738f8de1e1SXin LI size_t pagesize_len; 274268a55bcSHiroki Sato u_long ul; 275268a55bcSHiroki Sato 27679ba2f31SHiroki Sato /* Use built-in defaults for geli(8). */ 2778f8de1e1SXin LI aalgo = ealgo = keylen_str = ""; 278445bda3fSPawel Jakub Dawidek aflag = eflag = lflag = Tflag = ""; 279268a55bcSHiroki Sato 28079ba2f31SHiroki Sato /* We will always specify sectorsize. */ 2818f8de1e1SXin LI sflag = " -s "; 2828f8de1e1SXin LI sectorsize_str = NULL; 283268a55bcSHiroki Sato 2848f8de1e1SXin LI if (mntops != NULL) { 2858f8de1e1SXin LI string = ops = strdup(mntops); 286268a55bcSHiroki Sato 2878f8de1e1SXin LI while ((token = strsep(&string, ",")) != NULL) { 2888f8de1e1SXin LI if ((p = strstr(token, "aalgo=")) == token) { 289268a55bcSHiroki Sato aalgo = p + sizeof("aalgo=") - 1; 2908f8de1e1SXin LI aflag = " -a "; 2918f8de1e1SXin LI } else if ((p = strstr(token, "ealgo=")) == token) { 292268a55bcSHiroki Sato ealgo = p + sizeof("ealgo=") - 1; 2938f8de1e1SXin LI eflag = " -e "; 2948f8de1e1SXin LI } else if ((p = strstr(token, "keylen=")) == token) { 295268a55bcSHiroki Sato keylen_str = p + sizeof("keylen=") - 1; 296268a55bcSHiroki Sato errno = 0; 297268a55bcSHiroki Sato ul = strtoul(keylen_str, &p, 10); 298268a55bcSHiroki Sato if (errno == 0) { 299268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 300268a55bcSHiroki Sato errno = EINVAL; 301268a55bcSHiroki Sato } 302268a55bcSHiroki Sato if (errno) { 303268a55bcSHiroki Sato warn("Invalid keylen: %s", keylen_str); 3048f8de1e1SXin LI free(ops); 305268a55bcSHiroki Sato return (NULL); 306268a55bcSHiroki Sato } 3078f8de1e1SXin LI lflag = " -l "; 3088f8de1e1SXin LI } else if ((p = strstr(token, "sectorsize=")) == token) { 309268a55bcSHiroki Sato sectorsize_str = p + sizeof("sectorsize=") - 1; 310268a55bcSHiroki Sato errno = 0; 311268a55bcSHiroki Sato ul = strtoul(sectorsize_str, &p, 10); 312268a55bcSHiroki Sato if (errno == 0) { 313268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 314268a55bcSHiroki Sato errno = EINVAL; 315268a55bcSHiroki Sato } 316268a55bcSHiroki Sato if (errno) { 31779ba2f31SHiroki Sato warn("Invalid sectorsize: %s", 31879ba2f31SHiroki Sato sectorsize_str); 3198f8de1e1SXin LI free(ops); 320268a55bcSHiroki Sato return (NULL); 321268a55bcSHiroki Sato } 3228d27c200SDmitry Marakasov } else if (strcmp(token, "notrim") == 0) { 323a616b253SDoug Moore if (Eflag) { 324a616b253SDoug Moore warn("Options \"notrim\" and " 325a616b253SDoug Moore "\"trimonce\" conflict"); 326a616b253SDoug Moore free(ops); 327a616b253SDoug Moore return (NULL); 328a616b253SDoug Moore } 329445bda3fSPawel Jakub Dawidek Tflag = " -T "; 3308d27c200SDmitry Marakasov } else if (strcmp(token, "late") == 0) { 3318d27c200SDmitry Marakasov /* ignore known option */ 3328d27c200SDmitry Marakasov } else if (strcmp(token, "noauto") == 0) { 3338d27c200SDmitry Marakasov /* ignore known option */ 334a616b253SDoug Moore } else if (strcmp(token, "sw") == 0) { 335a616b253SDoug Moore /* ignore known option */ 336a616b253SDoug Moore } else if (strcmp(token, "trimonce") == 0) { 337a616b253SDoug Moore /* ignore known option */ 338a616b253SDoug Moore } else { 3398f8de1e1SXin LI warnx("Invalid option: %s", token); 3408f8de1e1SXin LI free(ops); 3418f8de1e1SXin LI return (NULL); 342268a55bcSHiroki Sato } 3438f8de1e1SXin LI } 3448f8de1e1SXin LI } else 3458f8de1e1SXin LI ops = NULL; 346268a55bcSHiroki Sato 3478f8de1e1SXin LI /* 3488f8de1e1SXin LI * If we do not have a sector size at this point, fill in 3498f8de1e1SXin LI * pagesize as sector size. 3508f8de1e1SXin LI */ 3518f8de1e1SXin LI if (sectorsize_str == NULL) { 35279ba2f31SHiroki Sato /* Use pagesize as default sectorsize. */ 3538f8de1e1SXin LI pagesize = getpagesize(); 3548f8de1e1SXin LI pagesize_len = snprintf(NULL, 0, "%d", pagesize) + 1; 3558f8de1e1SXin LI p = alloca(pagesize_len); 3568f8de1e1SXin LI snprintf(p, pagesize_len, "%d", pagesize); 3578f8de1e1SXin LI sectorsize_str = p; 3588f8de1e1SXin LI } 3598f8de1e1SXin LI 36024cd0f85SEnji Cooper (void)asprintf(&args, "%s%s%s%s%s%s%s%s%s -d", 361445bda3fSPawel Jakub Dawidek aflag, aalgo, eflag, ealgo, lflag, keylen_str, Tflag, 3628f8de1e1SXin LI sflag, sectorsize_str); 3638f8de1e1SXin LI 3648f8de1e1SXin LI free(ops); 3658f8de1e1SXin LI return (args); 3668f8de1e1SXin LI } 3678f8de1e1SXin LI 3688f8de1e1SXin LI static const char * 3698f8de1e1SXin LI swap_on_off_geli(const char *name, char *mntops, int doingall) 3708f8de1e1SXin LI { 3718f8de1e1SXin LI struct stat sb; 37279ba2f31SHiroki Sato char *dname, *args; 3738f8de1e1SXin LI int error; 3748f8de1e1SXin LI 3758f8de1e1SXin LI error = stat(name, &sb); 3768f8de1e1SXin LI 3778f8de1e1SXin LI if (which_prog == SWAPON) do { 37879ba2f31SHiroki Sato /* Skip if the .eli device already exists. */ 3798f8de1e1SXin LI if (error == 0) 3808f8de1e1SXin LI break; 3818f8de1e1SXin LI 3828f8de1e1SXin LI args = swap_on_geli_args(mntops); 3838f8de1e1SXin LI if (args == NULL) 3848f8de1e1SXin LI return (NULL); 3858f8de1e1SXin LI 3868f8de1e1SXin LI dname = swap_basename(name); 3878f8de1e1SXin LI if (dname == NULL) { 3888f8de1e1SXin LI free(args); 3898f8de1e1SXin LI return (NULL); 3908f8de1e1SXin LI } 3918f8de1e1SXin LI 3928f8de1e1SXin LI error = run_cmd(NULL, "%s onetime%s %s", _PATH_GELI, args, 393cb754f61SHiroki Sato dname); 3948f8de1e1SXin LI 3958f8de1e1SXin LI free(dname); 3968f8de1e1SXin LI free(args); 3978f8de1e1SXin LI 398268a55bcSHiroki Sato if (error) { 399b68ac800SPedro F. Giffuni /* error occurred during creation. */ 40079ba2f31SHiroki Sato if (qflag == 0) 4018f8de1e1SXin LI warnx("%s: Invalid parameters", name); 402268a55bcSHiroki Sato return (NULL); 403268a55bcSHiroki Sato } 4048f8de1e1SXin LI } while (0); 405268a55bcSHiroki Sato 406268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 407268a55bcSHiroki Sato } 408268a55bcSHiroki Sato 409268a55bcSHiroki Sato static const char * 4108f8de1e1SXin LI swap_on_off_md(const char *name, char *mntops, int doingall) 411268a55bcSHiroki Sato { 412268a55bcSHiroki Sato FILE *sfd; 413268a55bcSHiroki Sato int fd, mdunit, error; 414268a55bcSHiroki Sato const char *ret; 41554282733SXin LI static char mdpath[PATH_MAX], linebuf[PATH_MAX]; 416268a55bcSHiroki Sato char *p, *vnodefile; 417268a55bcSHiroki Sato size_t linelen; 418268a55bcSHiroki Sato u_long ul; 419268a55bcSHiroki Sato 420268a55bcSHiroki Sato fd = -1; 421268a55bcSHiroki Sato sfd = NULL; 422268a55bcSHiroki Sato if (strlen(name) == (sizeof(MD_NAME) - 1)) 423268a55bcSHiroki Sato mdunit = -1; 424268a55bcSHiroki Sato else { 425268a55bcSHiroki Sato errno = 0; 426268a55bcSHiroki Sato ul = strtoul(name + 2, &p, 10); 427268a55bcSHiroki Sato if (errno == 0) { 428268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 429268a55bcSHiroki Sato errno = EINVAL; 430268a55bcSHiroki Sato } 431268a55bcSHiroki Sato if (errno) { 432268a55bcSHiroki Sato warn("Bad device unit: %s", name); 433268a55bcSHiroki Sato return (NULL); 434268a55bcSHiroki Sato } 435268a55bcSHiroki Sato mdunit = (int)ul; 436268a55bcSHiroki Sato } 437268a55bcSHiroki Sato 438268a55bcSHiroki Sato vnodefile = NULL; 439268a55bcSHiroki Sato if ((p = strstr(mntops, "file=")) != NULL) { 440268a55bcSHiroki Sato vnodefile = strdup(p + sizeof("file=") - 1); 441268a55bcSHiroki Sato p = strchr(vnodefile, ','); 442268a55bcSHiroki Sato if (p != NULL) 443268a55bcSHiroki Sato *p = '\0'; 444268a55bcSHiroki Sato } 445268a55bcSHiroki Sato if (vnodefile == NULL) { 446268a55bcSHiroki Sato warnx("file option not found for %s", name); 447268a55bcSHiroki Sato return (NULL); 448268a55bcSHiroki Sato } 449268a55bcSHiroki Sato 4508f8de1e1SXin LI if (which_prog == SWAPON) { 451268a55bcSHiroki Sato if (mdunit == -1) { 452268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 453268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 454268a55bcSHiroki Sato if (error == 0) { 455268a55bcSHiroki Sato /* md device found. Ignore it. */ 456268a55bcSHiroki Sato close(fd); 457268a55bcSHiroki Sato if (!qflag) 458268a55bcSHiroki Sato warnx("%s: Device already in use", 459268a55bcSHiroki Sato vnodefile); 4601bf9e66cSXin LI free(vnodefile); 461268a55bcSHiroki Sato return (NULL); 462268a55bcSHiroki Sato } 463268a55bcSHiroki Sato error = run_cmd(&fd, "%s -a -t vnode -n -f %s", 464268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 465268a55bcSHiroki Sato if (error) { 466268a55bcSHiroki Sato warnx("mdconfig (attach) error: file=%s", 467268a55bcSHiroki Sato vnodefile); 4681bf9e66cSXin LI free(vnodefile); 469268a55bcSHiroki Sato return (NULL); 470268a55bcSHiroki Sato } 471268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 472268a55bcSHiroki Sato if (sfd == NULL) { 473268a55bcSHiroki Sato warn("mdconfig (attach) fdopen error"); 474268a55bcSHiroki Sato ret = NULL; 475268a55bcSHiroki Sato goto err; 476268a55bcSHiroki Sato } 477268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 4781bf6738fSDon Lewis if (p == NULL || 479268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf))) { 480268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output"); 481268a55bcSHiroki Sato ret = NULL; 482268a55bcSHiroki Sato goto err; 483268a55bcSHiroki Sato } 484883b7553SXin LI strlcpy(linebuf, p, linelen); 485268a55bcSHiroki Sato errno = 0; 486268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 487268a55bcSHiroki Sato if (errno == 0) { 488268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 489268a55bcSHiroki Sato errno = EINVAL; 490268a55bcSHiroki Sato } 491268a55bcSHiroki Sato if (errno) { 492268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output: %s", 493268a55bcSHiroki Sato linebuf); 494268a55bcSHiroki Sato ret = NULL; 495268a55bcSHiroki Sato goto err; 496268a55bcSHiroki Sato } 497268a55bcSHiroki Sato mdunit = (int)ul; 498268a55bcSHiroki Sato } else { 499268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 500268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 501268a55bcSHiroki Sato if (error == 0) { 502268a55bcSHiroki Sato /* md device found. Ignore it. */ 503268a55bcSHiroki Sato close(fd); 50479ba2f31SHiroki Sato if (qflag == 0) 505268a55bcSHiroki Sato warnx("md%d on %s: Device already " 506268a55bcSHiroki Sato "in use", mdunit, vnodefile); 5071bf9e66cSXin LI free(vnodefile); 508268a55bcSHiroki Sato return (NULL); 509268a55bcSHiroki Sato } 510268a55bcSHiroki Sato error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", 511268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit, vnodefile); 512268a55bcSHiroki Sato if (error) { 513268a55bcSHiroki Sato warnx("mdconfig (attach) error: " 514268a55bcSHiroki Sato "md%d on file=%s", mdunit, vnodefile); 5151bf9e66cSXin LI free(vnodefile); 516268a55bcSHiroki Sato return (NULL); 517268a55bcSHiroki Sato } 518268a55bcSHiroki Sato } 5198f8de1e1SXin LI } else /* SWAPOFF */ { 520268a55bcSHiroki Sato if (mdunit == -1) { 521268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 522268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 523268a55bcSHiroki Sato if (error) { 524268a55bcSHiroki Sato /* md device not found. Ignore it. */ 525268a55bcSHiroki Sato close(fd); 526268a55bcSHiroki Sato if (!qflag) 527268a55bcSHiroki Sato warnx("md on %s: Device not found", 528268a55bcSHiroki Sato vnodefile); 5291bf9e66cSXin LI free(vnodefile); 530268a55bcSHiroki Sato return (NULL); 531268a55bcSHiroki Sato } 532268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 533268a55bcSHiroki Sato if (sfd == NULL) { 534268a55bcSHiroki Sato warn("mdconfig (list) fdopen error"); 535268a55bcSHiroki Sato ret = NULL; 536268a55bcSHiroki Sato goto err; 537268a55bcSHiroki Sato } 538268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 539883b7553SXin LI if (p == NULL || 540883b7553SXin LI (linelen < 2 || linelen > sizeof(linebuf))) { 541268a55bcSHiroki Sato warn("mdconfig (list) unexpected output"); 542268a55bcSHiroki Sato ret = NULL; 543268a55bcSHiroki Sato goto err; 544268a55bcSHiroki Sato } 545883b7553SXin LI strlcpy(linebuf, p, linelen); 546268a55bcSHiroki Sato p = strchr(linebuf, ' '); 547268a55bcSHiroki Sato if (p != NULL) 548268a55bcSHiroki Sato *p = '\0'; 549268a55bcSHiroki Sato errno = 0; 550268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 551268a55bcSHiroki Sato if (errno == 0) { 552268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 553268a55bcSHiroki Sato errno = EINVAL; 554268a55bcSHiroki Sato } 555268a55bcSHiroki Sato if (errno) { 556268a55bcSHiroki Sato warn("mdconfig (list) unexpected output: %s", 557268a55bcSHiroki Sato linebuf); 558268a55bcSHiroki Sato ret = NULL; 559268a55bcSHiroki Sato goto err; 560268a55bcSHiroki Sato } 561268a55bcSHiroki Sato mdunit = (int)ul; 562268a55bcSHiroki Sato } else { 563268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 564268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 565268a55bcSHiroki Sato if (error) { 566268a55bcSHiroki Sato /* md device not found. Ignore it. */ 567268a55bcSHiroki Sato close(fd); 568268a55bcSHiroki Sato if (!qflag) 569268a55bcSHiroki Sato warnx("md%d on %s: Device not found", 570268a55bcSHiroki Sato mdunit, vnodefile); 5711bf9e66cSXin LI free(vnodefile); 572268a55bcSHiroki Sato return (NULL); 573268a55bcSHiroki Sato } 574268a55bcSHiroki Sato } 575268a55bcSHiroki Sato } 576268a55bcSHiroki Sato snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, 577268a55bcSHiroki Sato MD_NAME, mdunit); 578268a55bcSHiroki Sato mdpath[sizeof(mdpath) - 1] = '\0'; 579268a55bcSHiroki Sato ret = swap_on_off_sfile(mdpath, doingall); 580268a55bcSHiroki Sato 5818f8de1e1SXin LI if (which_prog == SWAPOFF) { 582268a55bcSHiroki Sato if (ret != NULL) { 583268a55bcSHiroki Sato error = run_cmd(NULL, "%s -d -u %d", 584268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit); 585268a55bcSHiroki Sato if (error) 586268a55bcSHiroki Sato warn("mdconfig (detach) detach failed: %s%s%d", 587268a55bcSHiroki Sato _PATH_DEV, MD_NAME, mdunit); 588268a55bcSHiroki Sato } 589268a55bcSHiroki Sato } 590268a55bcSHiroki Sato err: 591268a55bcSHiroki Sato if (sfd != NULL) 592268a55bcSHiroki Sato fclose(sfd); 593268a55bcSHiroki Sato if (fd != -1) 594268a55bcSHiroki Sato close(fd); 5951bf9e66cSXin LI free(vnodefile); 596268a55bcSHiroki Sato return (ret); 597268a55bcSHiroki Sato } 598268a55bcSHiroki Sato 599268a55bcSHiroki Sato static int 600268a55bcSHiroki Sato run_cmd(int *ofd, const char *cmdline, ...) 601268a55bcSHiroki Sato { 602268a55bcSHiroki Sato va_list ap; 603268a55bcSHiroki Sato char **argv, **argvp, *cmd, *p; 604268a55bcSHiroki Sato int argc, pid, status, rv; 605268a55bcSHiroki Sato int pfd[2], nfd, dup2dn; 606268a55bcSHiroki Sato 607268a55bcSHiroki Sato va_start(ap, cmdline); 608268a55bcSHiroki Sato rv = vasprintf(&cmd, cmdline, ap); 609268a55bcSHiroki Sato if (rv == -1) { 610268a55bcSHiroki Sato warn("%s", __func__); 61133c2e470SEnji Cooper va_end(ap); 612268a55bcSHiroki Sato return (rv); 613268a55bcSHiroki Sato } 614268a55bcSHiroki Sato va_end(ap); 615268a55bcSHiroki Sato 616268a55bcSHiroki Sato for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 617268a55bcSHiroki Sato argc++; 618268a55bcSHiroki Sato argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 619268a55bcSHiroki Sato for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 620268a55bcSHiroki Sato if (**argvp != '\0' && (++argvp > &argv[argc])) { 621268a55bcSHiroki Sato *argvp = NULL; 622268a55bcSHiroki Sato break; 623268a55bcSHiroki Sato } 624268a55bcSHiroki Sato /* The argv array ends up NULL-terminated here. */ 625268a55bcSHiroki Sato #if 0 626268a55bcSHiroki Sato { 627268a55bcSHiroki Sato int i; 628268a55bcSHiroki Sato 629268a55bcSHiroki Sato fprintf(stderr, "DEBUG: running:"); 630268a55bcSHiroki Sato /* Should be equivalent to 'cmd' (before strsep, of course). */ 631268a55bcSHiroki Sato for (i = 0; argv[i] != NULL; i++) 632268a55bcSHiroki Sato fprintf(stderr, " %s", argv[i]); 633268a55bcSHiroki Sato fprintf(stderr, "\n"); 634268a55bcSHiroki Sato } 635268a55bcSHiroki Sato #endif 636268a55bcSHiroki Sato dup2dn = 1; 637268a55bcSHiroki Sato if (ofd != NULL) { 638268a55bcSHiroki Sato if (pipe(&pfd[0]) == -1) { 639268a55bcSHiroki Sato warn("%s: pipe", __func__); 640268a55bcSHiroki Sato return (-1); 641268a55bcSHiroki Sato } 642268a55bcSHiroki Sato *ofd = pfd[0]; 643268a55bcSHiroki Sato dup2dn = 0; 644268a55bcSHiroki Sato } 645268a55bcSHiroki Sato pid = fork(); 646268a55bcSHiroki Sato switch (pid) { 647268a55bcSHiroki Sato case 0: 648268a55bcSHiroki Sato /* Child process. */ 649268a55bcSHiroki Sato if (ofd != NULL) 650268a55bcSHiroki Sato if (dup2(pfd[1], STDOUT_FILENO) < 0) 651268a55bcSHiroki Sato err(1, "dup2 in %s", __func__); 652268a55bcSHiroki Sato nfd = open(_PATH_DEVNULL, O_RDWR); 653268a55bcSHiroki Sato if (nfd == -1) 654268a55bcSHiroki Sato err(1, "%s: open %s", __func__, _PATH_DEVNULL); 655268a55bcSHiroki Sato if (dup2(nfd, STDIN_FILENO) < 0) 656268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 657268a55bcSHiroki Sato if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0) 658268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 659268a55bcSHiroki Sato if (dup2(nfd, STDERR_FILENO) < 0) 660268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 661268a55bcSHiroki Sato execv(argv[0], argv); 662268a55bcSHiroki Sato warn("exec: %s", argv[0]); 663268a55bcSHiroki Sato _exit(-1); 664268a55bcSHiroki Sato case -1: 665268a55bcSHiroki Sato err(1, "%s: fork", __func__); 666268a55bcSHiroki Sato } 667268a55bcSHiroki Sato free(cmd); 668268a55bcSHiroki Sato free(argv); 669268a55bcSHiroki Sato while (waitpid(pid, &status, 0) != pid) 670268a55bcSHiroki Sato ; 671268a55bcSHiroki Sato return (WEXITSTATUS(status)); 672268a55bcSHiroki Sato } 673268a55bcSHiroki Sato 6746d5685c7SDoug Moore static int 6756d5685c7SDoug Moore swapon_trim(const char *name) 676a616b253SDoug Moore { 677a616b253SDoug Moore struct stat sb; 678a616b253SDoug Moore off_t ioarg[2], sz; 6796d5685c7SDoug Moore int error, fd; 680a616b253SDoug Moore 681473fe2c0SDoug Moore /* Open a descriptor to create a consumer of the device. */ 682a616b253SDoug Moore fd = open(name, O_WRONLY); 683a616b253SDoug Moore if (fd < 0) 684a616b253SDoug Moore errx(1, "Cannot open %s", name); 685473fe2c0SDoug Moore /* Find the device size. */ 686a616b253SDoug Moore if (fstat(fd, &sb) < 0) 687a616b253SDoug Moore errx(1, "Cannot stat %s", name); 688a616b253SDoug Moore if (S_ISREG(sb.st_mode)) 689a616b253SDoug Moore sz = sb.st_size; 6909035b225SDoug Moore else if (S_ISCHR(sb.st_mode)) { 691a616b253SDoug Moore if (ioctl(fd, DIOCGMEDIASIZE, &sz) != 0) 692a616b253SDoug Moore err(1, "ioctl(DIOCGMEDIASIZE)"); 693a616b253SDoug Moore } else 694a616b253SDoug Moore errx(1, "%s has an invalid file type", name); 695473fe2c0SDoug Moore /* Trim the device. */ 696504f5e29SDoug Moore ioarg[0] = BBSIZE; 697504f5e29SDoug Moore ioarg[1] = sz - BBSIZE; 698a616b253SDoug Moore if (ioctl(fd, DIOCGDELETE, ioarg) != 0) 699a616b253SDoug Moore warn("ioctl(DIOCGDELETE)"); 7006d5685c7SDoug Moore 701473fe2c0SDoug Moore /* Start using the device for swapping, creating a second consumer. */ 7026d5685c7SDoug Moore error = swapon(name); 703473fe2c0SDoug Moore 704473fe2c0SDoug Moore /* 705473fe2c0SDoug Moore * Do not close the device until the swap pager has attempted to create 706473fe2c0SDoug Moore * another consumer. For GELI devices created with the 'detach -l' 707473fe2c0SDoug Moore * option, removing the last consumer causes the device to be detached 708473fe2c0SDoug Moore * - that is, to disappear. This ordering ensures that the device will 709473fe2c0SDoug Moore * not be detached until swapoff is called. 710473fe2c0SDoug Moore */ 711a616b253SDoug Moore close(fd); 7126d5685c7SDoug Moore return (error); 713a616b253SDoug Moore } 714a616b253SDoug Moore 715268a55bcSHiroki Sato static const char * 7168f8de1e1SXin LI swap_on_off_sfile(const char *name, int doingall) 717268a55bcSHiroki Sato { 718268a55bcSHiroki Sato int error; 719268a55bcSHiroki Sato 7206d5685c7SDoug Moore if (which_prog == SWAPON) 7216d5685c7SDoug Moore error = Eflag ? swapon_trim(name) : swapon(name); 722b49b6e0fSKonstantin Belousov else /* SWAPOFF */ 723b49b6e0fSKonstantin Belousov error = swapoff(name, fflag ? SWAPOFF_FORCE : 0); 7248f8de1e1SXin LI 725268a55bcSHiroki Sato if (error == -1) { 7268fae3551SRodney W. Grimes switch (errno) { 7278fae3551SRodney W. Grimes case EBUSY: 72879ba2f31SHiroki Sato if (doingall == 0) 729268a55bcSHiroki Sato warnx("%s: Device already in use", name); 7308fae3551SRodney W. Grimes break; 7314937798dSDavid Schultz case EINVAL: 7324937798dSDavid Schultz if (which_prog == SWAPON) 7334937798dSDavid Schultz warnx("%s: NSWAPDEV limit reached", name); 73479ba2f31SHiroki Sato else if (doingall == 0) 7354937798dSDavid Schultz warn("%s", name); 7364937798dSDavid Schultz break; 7378fae3551SRodney W. Grimes default: 7386da7f378SPhilippe Charnier warn("%s", name); 7398fae3551SRodney W. Grimes break; 7408fae3551SRodney W. Grimes } 741268a55bcSHiroki Sato return (NULL); 7428fae3551SRodney W. Grimes } 743268a55bcSHiroki Sato return (name); 7448fae3551SRodney W. Grimes } 7458fae3551SRodney W. Grimes 7466da7f378SPhilippe Charnier static void 747a420c811SMatthew Dillon usage(void) 7488fae3551SRodney W. Grimes { 74979ba2f31SHiroki Sato 750a420c811SMatthew Dillon fprintf(stderr, "usage: %s ", getprogname()); 751a420c811SMatthew Dillon switch(orig_prog) { 752a420c811SMatthew Dillon case SWAPON: 753a616b253SDoug Moore fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n"); 754a616b253SDoug Moore break; 7558d646af5SRuslan Ermilov case SWAPOFF: 7561aa249c9SKonstantin Belousov fprintf(stderr, "[-F fstab] -afLq | file ...\n"); 757a420c811SMatthew Dillon break; 758a420c811SMatthew Dillon case SWAPCTL: 7592e64768cSPawel Jakub Dawidek fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 760a420c811SMatthew Dillon break; 761a420c811SMatthew Dillon } 7628fae3551SRodney W. Grimes exit(1); 7638fae3551SRodney W. Grimes } 76492da00bbSMatthew Dillon 765a420c811SMatthew Dillon static void 7662e64768cSPawel Jakub Dawidek sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 7672e64768cSPawel Jakub Dawidek long blocksize) 7682e64768cSPawel Jakub Dawidek { 7692e64768cSPawel Jakub Dawidek char tmp[16]; 7702e64768cSPawel Jakub Dawidek 77179ba2f31SHiroki Sato if (hflag == 'H') { 7722e64768cSPawel Jakub Dawidek humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 7732e64768cSPawel Jakub Dawidek HN_B | HN_NOSPACE | HN_DECIMAL); 7742e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*s", hlen, tmp); 77579ba2f31SHiroki Sato } else 7762e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 7772e64768cSPawel Jakub Dawidek } 7782e64768cSPawel Jakub Dawidek 7792e64768cSPawel Jakub Dawidek static void 780a420c811SMatthew Dillon swaplist(int lflag, int sflag, int hflag) 78192da00bbSMatthew Dillon { 782a420c811SMatthew Dillon size_t mibsize, size; 783a420c811SMatthew Dillon struct xswdev xsw; 78469095b02SMike Barcroft int hlen, mib[16], n, pagesize; 785a420c811SMatthew Dillon long blocksize; 786a420c811SMatthew Dillon long long total = 0; 787a420c811SMatthew Dillon long long used = 0; 788a420c811SMatthew Dillon long long tmp_total; 789a420c811SMatthew Dillon long long tmp_used; 7902e64768cSPawel Jakub Dawidek char buf[32]; 79192da00bbSMatthew Dillon 792a420c811SMatthew Dillon pagesize = getpagesize(); 793a420c811SMatthew Dillon switch(hflag) { 7942e64768cSPawel Jakub Dawidek case 'G': 7952e64768cSPawel Jakub Dawidek blocksize = 1024 * 1024 * 1024; 7962e64768cSPawel Jakub Dawidek strlcpy(buf, "1GB-blocks", sizeof(buf)); 7972e64768cSPawel Jakub Dawidek hlen = 10; 7982e64768cSPawel Jakub Dawidek break; 7992e64768cSPawel Jakub Dawidek case 'H': 8002e64768cSPawel Jakub Dawidek blocksize = -1; 8012e64768cSPawel Jakub Dawidek strlcpy(buf, "Bytes", sizeof(buf)); 8022e64768cSPawel Jakub Dawidek hlen = 10; 8032e64768cSPawel Jakub Dawidek break; 804a420c811SMatthew Dillon case 'K': 805a420c811SMatthew Dillon blocksize = 1024; 8062e64768cSPawel Jakub Dawidek strlcpy(buf, "1kB-blocks", sizeof(buf)); 807a420c811SMatthew Dillon hlen = 10; 808a420c811SMatthew Dillon break; 809a420c811SMatthew Dillon case 'M': 810a420c811SMatthew Dillon blocksize = 1024 * 1024; 8112e64768cSPawel Jakub Dawidek strlcpy(buf, "1MB-blocks", sizeof(buf)); 812a420c811SMatthew Dillon hlen = 10; 813a420c811SMatthew Dillon break; 814a420c811SMatthew Dillon default: 8159255f327SMike Barcroft getbsize(&hlen, &blocksize); 8162e64768cSPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 817a420c811SMatthew Dillon break; 81892da00bbSMatthew Dillon } 819a420c811SMatthew Dillon 82079ba2f31SHiroki Sato mibsize = nitems(mib); 821a420c811SMatthew Dillon if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 822a420c811SMatthew Dillon err(1, "sysctlnametomib()"); 823a420c811SMatthew Dillon 824a420c811SMatthew Dillon if (lflag) { 825a420c811SMatthew Dillon printf("%-13s %*s %*s\n", 826a420c811SMatthew Dillon "Device:", 827a420c811SMatthew Dillon hlen, buf, 828a420c811SMatthew Dillon hlen, "Used:"); 829a420c811SMatthew Dillon } 830a420c811SMatthew Dillon 831a420c811SMatthew Dillon for (n = 0; ; ++n) { 832a420c811SMatthew Dillon mib[mibsize] = n; 833a420c811SMatthew Dillon size = sizeof xsw; 83416fc3635SMark Murray if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 835a420c811SMatthew Dillon break; 836a420c811SMatthew Dillon if (xsw.xsw_version != XSWDEV_VERSION) 837a420c811SMatthew Dillon errx(1, "xswdev version mismatch"); 838a420c811SMatthew Dillon 8392e64768cSPawel Jakub Dawidek tmp_total = (long long)xsw.xsw_nblks * pagesize; 8402e64768cSPawel Jakub Dawidek tmp_used = (long long)xsw.xsw_used * pagesize; 841a420c811SMatthew Dillon total += tmp_total; 842a420c811SMatthew Dillon used += tmp_used; 843a420c811SMatthew Dillon if (lflag) { 8442e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 8452e64768cSPawel Jakub Dawidek blocksize); 8462e64768cSPawel Jakub Dawidek printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 8472e64768cSPawel Jakub Dawidek buf); 8482e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 8492e64768cSPawel Jakub Dawidek blocksize); 8502e64768cSPawel Jakub Dawidek printf("%s\n", buf); 851a420c811SMatthew Dillon } 852a420c811SMatthew Dillon } 853a420c811SMatthew Dillon if (errno != ENOENT) 854a420c811SMatthew Dillon err(1, "sysctl()"); 855a420c811SMatthew Dillon 856a420c811SMatthew Dillon if (sflag) { 8572e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 8582e64768cSPawel Jakub Dawidek printf("Total: %s ", buf); 8592e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 8602e64768cSPawel Jakub Dawidek printf("%s\n", buf); 861a420c811SMatthew Dillon } 862a420c811SMatthew Dillon } 863a420c811SMatthew Dillon 864