179ba2f31SHiroki Sato /*- 28fae3551SRodney W. Grimes * Copyright (c) 1980, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 148fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 158fae3551SRodney W. Grimes * without specific prior written permission. 168fae3551SRodney W. Grimes * 178fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278fae3551SRodney W. Grimes * SUCH DAMAGE. 288fae3551SRodney W. Grimes */ 298fae3551SRodney W. Grimes 30c69284caSDavid E. O'Brien #if 0 318fae3551SRodney W. Grimes #ifndef lint 32e798a806SPhilippe Charnier static const char copyright[] = 338fae3551SRodney W. Grimes "@(#) Copyright (c) 1980, 1993\n\ 348fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 358fae3551SRodney W. Grimes #endif /* not lint */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 388fae3551SRodney W. Grimes static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93"; 398fae3551SRodney W. Grimes #endif /* not lint */ 40c69284caSDavid E. O'Brien #endif 41c69284caSDavid E. O'Brien #include <sys/cdefs.h> 42c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 438fae3551SRodney W. Grimes 44a420c811SMatthew Dillon #include <sys/param.h> 45268a55bcSHiroki Sato #include <sys/types.h> 46268a55bcSHiroki Sato #include <sys/mdioctl.h> 47268a55bcSHiroki Sato #include <sys/stat.h> 48a420c811SMatthew Dillon #include <sys/sysctl.h> 49268a55bcSHiroki Sato #include <sys/wait.h> 506004362eSDavid Schultz #include <vm/vm_param.h> 51a420c811SMatthew Dillon 526da7f378SPhilippe Charnier #include <err.h> 53e798a806SPhilippe Charnier #include <errno.h> 54268a55bcSHiroki Sato #include <fcntl.h> 55268a55bcSHiroki Sato #include <fnmatch.h> 56e798a806SPhilippe Charnier #include <fstab.h> 57268a55bcSHiroki Sato #include <libgen.h> 58268a55bcSHiroki Sato #include <libutil.h> 59268a55bcSHiroki Sato #include <limits.h> 60268a55bcSHiroki Sato #include <paths.h> 61268a55bcSHiroki Sato #include <stdarg.h> 62e798a806SPhilippe Charnier #include <stdio.h> 63cafefe8cSDima Dorfman #include <stdlib.h> 64e798a806SPhilippe Charnier #include <string.h> 65e798a806SPhilippe Charnier #include <unistd.h> 668fae3551SRodney W. Grimes 67a420c811SMatthew Dillon static void usage(void); 688f8de1e1SXin LI static const char *swap_on_off(const char *, int, char *); 698f8de1e1SXin LI static const char *swap_on_off_gbde(const char *, int); 708f8de1e1SXin LI static const char *swap_on_off_geli(const char *, char *, int); 718f8de1e1SXin LI static const char *swap_on_off_md(const char *, char *, int); 728f8de1e1SXin LI static const char *swap_on_off_sfile(const char *, int); 73a420c811SMatthew Dillon static void swaplist(int, int, int); 74268a55bcSHiroki Sato static int run_cmd(int *, const char *, ...) __printflike(2, 3); 75a420c811SMatthew Dillon 761efe3c6bSEd Schouten static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 7738994f93SPoul-Henning Kamp 78268a55bcSHiroki Sato static int qflag; 79268a55bcSHiroki Sato 8038994f93SPoul-Henning Kamp int 8138994f93SPoul-Henning Kamp main(int argc, char **argv) 828fae3551SRodney W. Grimes { 833d438ad6SDavid E. O'Brien struct fstab *fsp; 84268a55bcSHiroki Sato const char *swfile; 85a420c811SMatthew Dillon char *ptr; 8679ba2f31SHiroki Sato int ret, ch, doall; 8779ba2f31SHiroki Sato int sflag, lflag, late, hflag; 88633d2bc5SMaxim Sobolev const char *etc_fstab; 8992da00bbSMatthew Dillon 9079ba2f31SHiroki Sato sflag = lflag = late = hflag = 0; 91a420c811SMatthew Dillon if ((ptr = strrchr(argv[0], '/')) == NULL) 92a420c811SMatthew Dillon ptr = argv[0]; 9379ba2f31SHiroki Sato if (strstr(ptr, "swapon") != NULL) 94a420c811SMatthew Dillon which_prog = SWAPON; 9579ba2f31SHiroki Sato else if (strstr(ptr, "swapoff") != NULL) 96a420c811SMatthew Dillon which_prog = SWAPOFF; 97a420c811SMatthew Dillon orig_prog = which_prog; 988fae3551SRodney W. Grimes 998fae3551SRodney W. Grimes doall = 0; 100633d2bc5SMaxim Sobolev etc_fstab = NULL; 101268a55bcSHiroki Sato while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) { 102a420c811SMatthew Dillon switch(ch) { 103a420c811SMatthew Dillon case 'A': 104a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 1058fae3551SRodney W. Grimes doall = 1; 106a420c811SMatthew Dillon which_prog = SWAPON; 10779ba2f31SHiroki Sato } else 108a420c811SMatthew Dillon usage(); 109a420c811SMatthew Dillon break; 110a420c811SMatthew Dillon case 'a': 111a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) 112a420c811SMatthew Dillon doall = 1; 113a420c811SMatthew Dillon else 114a420c811SMatthew Dillon which_prog = SWAPON; 115a420c811SMatthew Dillon break; 116a420c811SMatthew Dillon case 'd': 117a420c811SMatthew Dillon if (which_prog == SWAPCTL) 118a420c811SMatthew Dillon which_prog = SWAPOFF; 119a420c811SMatthew Dillon else 120a420c811SMatthew Dillon usage(); 121a420c811SMatthew Dillon break; 1222e64768cSPawel Jakub Dawidek case 'g': 1232e64768cSPawel Jakub Dawidek hflag = 'G'; 1242e64768cSPawel Jakub Dawidek break; 1252e64768cSPawel Jakub Dawidek case 'h': 1262e64768cSPawel Jakub Dawidek hflag = 'H'; 1272e64768cSPawel Jakub Dawidek break; 1282e64768cSPawel Jakub Dawidek case 'k': 1292e64768cSPawel Jakub Dawidek hflag = 'K'; 130a420c811SMatthew Dillon break; 131a420c811SMatthew Dillon case 'l': 132a420c811SMatthew Dillon lflag = 1; 133a420c811SMatthew Dillon break; 134268a55bcSHiroki Sato case 'L': 135268a55bcSHiroki Sato late = 1; 136268a55bcSHiroki Sato break; 1372e64768cSPawel Jakub Dawidek case 'm': 138a420c811SMatthew Dillon hflag = 'M'; 139a420c811SMatthew Dillon break; 14045a5dc93SMike Makonnen case 'q': 14145a5dc93SMike Makonnen if (which_prog == SWAPON || which_prog == SWAPOFF) 14245a5dc93SMike Makonnen qflag = 1; 14345a5dc93SMike Makonnen break; 1442e64768cSPawel Jakub Dawidek case 's': 1452e64768cSPawel Jakub Dawidek sflag = 1; 146a420c811SMatthew Dillon break; 147a420c811SMatthew Dillon case 'U': 148a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 149a420c811SMatthew Dillon doall = 1; 150a420c811SMatthew Dillon which_prog = SWAPOFF; 15179ba2f31SHiroki Sato } else 152a420c811SMatthew Dillon usage(); 1538fae3551SRodney W. Grimes break; 154633d2bc5SMaxim Sobolev case 'F': 155633d2bc5SMaxim Sobolev etc_fstab = optarg; 156633d2bc5SMaxim Sobolev break; 1578fae3551SRodney W. Grimes case '?': 1588fae3551SRodney W. Grimes default: 159a420c811SMatthew Dillon usage(); 160a420c811SMatthew Dillon } 1618fae3551SRodney W. Grimes } 1628fae3551SRodney W. Grimes argv += optind; 1638fae3551SRodney W. Grimes 164ce458f42SEd Schouten ret = 0; 165268a55bcSHiroki Sato swfile = NULL; 166633d2bc5SMaxim Sobolev if (etc_fstab != NULL) 167633d2bc5SMaxim Sobolev setfstab(etc_fstab); 168a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) { 169a420c811SMatthew Dillon if (doall) { 17038994f93SPoul-Henning Kamp while ((fsp = getfsent()) != NULL) { 1714139627dSHiroki Sato if (strcmp(fsp->fs_type, FSTAB_SW) != 0) 1728fae3551SRodney W. Grimes continue; 1734139627dSHiroki Sato if (strstr(fsp->fs_mntops, "noauto") != NULL) 1747fc4a454SJordan K. Hubbard continue; 175268a55bcSHiroki Sato if (which_prog != SWAPOFF && 176*1482f982SHiroki Sato strstr(fsp->fs_mntops, "late") && 1774139627dSHiroki Sato late == 0) 178268a55bcSHiroki Sato continue; 179268a55bcSHiroki Sato swfile = swap_on_off(fsp->fs_spec, 1, 180268a55bcSHiroki Sato fsp->fs_mntops); 181268a55bcSHiroki Sato if (swfile == NULL) { 182ce458f42SEd Schouten ret = 1; 183268a55bcSHiroki Sato continue; 184268a55bcSHiroki Sato } 18579ba2f31SHiroki Sato if (qflag == 0) { 18692da00bbSMatthew Dillon printf("%s: %sing %s as swap device\n", 18745a5dc93SMike Makonnen getprogname(), 188268a55bcSHiroki Sato (which_prog == SWAPOFF) ? 189268a55bcSHiroki Sato "remov" : "add", swfile); 190a420c811SMatthew Dillon } 191a420c811SMatthew Dillon } 19279ba2f31SHiroki Sato } else if (*argv == NULL) 193a420c811SMatthew Dillon usage(); 194a420c811SMatthew Dillon for (; *argv; ++argv) { 195268a55bcSHiroki Sato swfile = swap_on_off(*argv, 0, NULL); 196268a55bcSHiroki Sato if (swfile == NULL) { 197ce458f42SEd Schouten ret = 1; 198268a55bcSHiroki Sato continue; 199268a55bcSHiroki Sato } 200268a55bcSHiroki Sato if (orig_prog == SWAPCTL) { 201a420c811SMatthew Dillon printf("%s: %sing %s as swap device\n", 202268a55bcSHiroki Sato getprogname(), 203268a55bcSHiroki Sato (which_prog == SWAPOFF) ? "remov" : "add", 204268a55bcSHiroki Sato swfile); 205a420c811SMatthew Dillon } 206a420c811SMatthew Dillon } 207a420c811SMatthew Dillon } else { 208a420c811SMatthew Dillon if (lflag || sflag) 209a420c811SMatthew Dillon swaplist(lflag, sflag, hflag); 210a420c811SMatthew Dillon else 211a420c811SMatthew Dillon usage(); 212a420c811SMatthew Dillon } 213ce458f42SEd Schouten exit(ret); 2148fae3551SRodney W. Grimes } 2158fae3551SRodney W. Grimes 216268a55bcSHiroki Sato static const char * 2178f8de1e1SXin LI swap_on_off(const char *name, int doingall, char *mntops) 2188fae3551SRodney W. Grimes { 219268a55bcSHiroki Sato char base[PATH_MAX]; 220268a55bcSHiroki Sato 221268a55bcSHiroki Sato /* Swap on vnode-backed md(4) device. */ 222268a55bcSHiroki Sato if (mntops != NULL && 2238f8de1e1SXin LI (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || 2248f8de1e1SXin LI fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || 225268a55bcSHiroki Sato strncmp(_PATH_DEV MD_NAME, name, 226268a55bcSHiroki Sato sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || 227268a55bcSHiroki Sato strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) 228268a55bcSHiroki Sato return (swap_on_off_md(name, mntops, doingall)); 229268a55bcSHiroki Sato 230268a55bcSHiroki Sato basename_r(name, base); 2318f8de1e1SXin LI 2328f8de1e1SXin LI /* Swap on encrypted device by GEOM_BDE. */ 2338f8de1e1SXin LI if (fnmatch("*.bde", base, 0) == 0) 234268a55bcSHiroki Sato return (swap_on_off_gbde(name, doingall)); 235268a55bcSHiroki Sato 236268a55bcSHiroki Sato /* Swap on encrypted device by GEOM_ELI. */ 2378f8de1e1SXin LI if (fnmatch("*.eli", base, 0) == 0) 238268a55bcSHiroki Sato return (swap_on_off_geli(name, mntops, doingall)); 239268a55bcSHiroki Sato 240268a55bcSHiroki Sato /* Swap on special file. */ 241268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 242268a55bcSHiroki Sato } 243268a55bcSHiroki Sato 2448f8de1e1SXin LI /* Strip off .bde or .eli suffix from swap device name */ 2458f8de1e1SXin LI static char * 2468f8de1e1SXin LI swap_basename(const char *name) 247268a55bcSHiroki Sato { 248cb754f61SHiroki Sato char *dname, *p; 249268a55bcSHiroki Sato 250cb754f61SHiroki Sato dname = strdup(name); 251cb754f61SHiroki Sato p = strrchr(dname, '.'); 2528f8de1e1SXin LI /* assert(p != NULL); */ 253268a55bcSHiroki Sato *p = '\0'; 254268a55bcSHiroki Sato 2558f8de1e1SXin LI return (dname); 2568f8de1e1SXin LI } 2578f8de1e1SXin LI 2588f8de1e1SXin LI static const char * 2598f8de1e1SXin LI swap_on_off_gbde(const char *name, int doingall) 2608f8de1e1SXin LI { 2618f8de1e1SXin LI const char *ret; 2621fdb18b0SJilles Tjoelker char pass[64 * 2 + 1]; 2631fdb18b0SJilles Tjoelker unsigned char bpass[64]; 2648f8de1e1SXin LI char *dname; 2658f8de1e1SXin LI int i, error; 2668f8de1e1SXin LI 2678f8de1e1SXin LI dname = swap_basename(name); 2688f8de1e1SXin LI if (dname == NULL) 2698f8de1e1SXin LI return (NULL); 2708f8de1e1SXin LI 2718f8de1e1SXin LI if (which_prog == SWAPON) { 272268a55bcSHiroki Sato arc4random_buf(bpass, sizeof(bpass)); 273268a55bcSHiroki Sato for (i = 0; i < (int)sizeof(bpass); i++) 274268a55bcSHiroki Sato sprintf(&pass[2 * i], "%02x", bpass[i]); 275268a55bcSHiroki Sato pass[sizeof(pass) - 1] = '\0'; 276268a55bcSHiroki Sato 2778f8de1e1SXin LI error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE, 278cb754f61SHiroki Sato dname, pass); 279268a55bcSHiroki Sato if (error) { 280268a55bcSHiroki Sato /* bde device found. Ignore it. */ 2818f8de1e1SXin LI free(dname); 28279ba2f31SHiroki Sato if (qflag == 0) 283268a55bcSHiroki Sato warnx("%s: Device already in use", name); 284268a55bcSHiroki Sato return (NULL); 285268a55bcSHiroki Sato } 2868f8de1e1SXin LI error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE, 287cb754f61SHiroki Sato dname, pass); 2888f8de1e1SXin LI free(dname); 289268a55bcSHiroki Sato if (error) { 290268a55bcSHiroki Sato warnx("gbde (attach) error: %s", name); 291268a55bcSHiroki Sato return (NULL); 292268a55bcSHiroki Sato } 293268a55bcSHiroki Sato } 2948f8de1e1SXin LI 295268a55bcSHiroki Sato ret = swap_on_off_sfile(name, doingall); 296268a55bcSHiroki Sato 2978f8de1e1SXin LI if (which_prog == SWAPOFF) { 2988f8de1e1SXin LI error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname); 2998f8de1e1SXin LI free(dname); 300268a55bcSHiroki Sato if (error) { 301268a55bcSHiroki Sato /* bde device not found. Ignore it. */ 30279ba2f31SHiroki Sato if (qflag == 0) 3038f8de1e1SXin LI warnx("%s: Device not found", name); 304268a55bcSHiroki Sato return (NULL); 305268a55bcSHiroki Sato } 306268a55bcSHiroki Sato } 307268a55bcSHiroki Sato 308268a55bcSHiroki Sato return (ret); 309268a55bcSHiroki Sato } 310268a55bcSHiroki Sato 3110d8a14f9SXin LI /* Build geli(8) arguments from mntops */ 3128f8de1e1SXin LI static char * 3138f8de1e1SXin LI swap_on_geli_args(const char *mntops) 314268a55bcSHiroki Sato { 3158f8de1e1SXin LI const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; 3168f8de1e1SXin LI const char *aflag, *eflag, *lflag, *sflag; 31779ba2f31SHiroki Sato char *p, *args, *token, *string, *ops; 3188f8de1e1SXin LI int argsize, pagesize; 3198f8de1e1SXin LI size_t pagesize_len; 320268a55bcSHiroki Sato u_long ul; 321268a55bcSHiroki Sato 32279ba2f31SHiroki Sato /* Use built-in defaults for geli(8). */ 3238f8de1e1SXin LI aalgo = ealgo = keylen_str = ""; 3248f8de1e1SXin LI aflag = eflag = lflag = ""; 325268a55bcSHiroki Sato 32679ba2f31SHiroki Sato /* We will always specify sectorsize. */ 3278f8de1e1SXin LI sflag = " -s "; 3288f8de1e1SXin LI sectorsize_str = NULL; 329268a55bcSHiroki Sato 3308f8de1e1SXin LI if (mntops != NULL) { 3318f8de1e1SXin LI string = ops = strdup(mntops); 332268a55bcSHiroki Sato 3338f8de1e1SXin LI while ((token = strsep(&string, ",")) != NULL) { 3348f8de1e1SXin LI if ((p = strstr(token, "aalgo=")) == token) { 335268a55bcSHiroki Sato aalgo = p + sizeof("aalgo=") - 1; 3368f8de1e1SXin LI aflag = " -a "; 3378f8de1e1SXin LI } else if ((p = strstr(token, "ealgo=")) == token) { 338268a55bcSHiroki Sato ealgo = p + sizeof("ealgo=") - 1; 3398f8de1e1SXin LI eflag = " -e "; 3408f8de1e1SXin LI } else if ((p = strstr(token, "keylen=")) == token) { 341268a55bcSHiroki Sato keylen_str = p + sizeof("keylen=") - 1; 342268a55bcSHiroki Sato errno = 0; 343268a55bcSHiroki Sato ul = strtoul(keylen_str, &p, 10); 344268a55bcSHiroki Sato if (errno == 0) { 345268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 346268a55bcSHiroki Sato errno = EINVAL; 347268a55bcSHiroki Sato } 348268a55bcSHiroki Sato if (errno) { 349268a55bcSHiroki Sato warn("Invalid keylen: %s", keylen_str); 3508f8de1e1SXin LI free(ops); 351268a55bcSHiroki Sato return (NULL); 352268a55bcSHiroki Sato } 3538f8de1e1SXin LI lflag = " -l "; 3548f8de1e1SXin LI } else if ((p = strstr(token, "sectorsize=")) == token) { 355268a55bcSHiroki Sato sectorsize_str = p + sizeof("sectorsize=") - 1; 356268a55bcSHiroki Sato errno = 0; 357268a55bcSHiroki Sato ul = strtoul(sectorsize_str, &p, 10); 358268a55bcSHiroki Sato if (errno == 0) { 359268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 360268a55bcSHiroki Sato errno = EINVAL; 361268a55bcSHiroki Sato } 362268a55bcSHiroki Sato if (errno) { 36379ba2f31SHiroki Sato warn("Invalid sectorsize: %s", 36479ba2f31SHiroki Sato sectorsize_str); 3658f8de1e1SXin LI free(ops); 366268a55bcSHiroki Sato return (NULL); 367268a55bcSHiroki Sato } 3688f8de1e1SXin LI } else if (strcmp(token, "sw") != 0) { 3698f8de1e1SXin LI warnx("Invalid option: %s", token); 3708f8de1e1SXin LI free(ops); 3718f8de1e1SXin LI return (NULL); 372268a55bcSHiroki Sato } 3738f8de1e1SXin LI } 3748f8de1e1SXin LI } else 3758f8de1e1SXin LI ops = NULL; 376268a55bcSHiroki Sato 3778f8de1e1SXin LI /* 3788f8de1e1SXin LI * If we do not have a sector size at this point, fill in 3798f8de1e1SXin LI * pagesize as sector size. 3808f8de1e1SXin LI */ 3818f8de1e1SXin LI if (sectorsize_str == NULL) { 38279ba2f31SHiroki Sato /* Use pagesize as default sectorsize. */ 3838f8de1e1SXin LI pagesize = getpagesize(); 3848f8de1e1SXin LI pagesize_len = snprintf(NULL, 0, "%d", pagesize) + 1; 3858f8de1e1SXin LI p = alloca(pagesize_len); 3868f8de1e1SXin LI snprintf(p, pagesize_len, "%d", pagesize); 3878f8de1e1SXin LI sectorsize_str = p; 3888f8de1e1SXin LI } 3898f8de1e1SXin LI 3908f8de1e1SXin LI argsize = asprintf(&args, "%s%s%s%s%s%s%s%s -d", 3918f8de1e1SXin LI aflag, aalgo, eflag, ealgo, lflag, keylen_str, 3928f8de1e1SXin LI sflag, sectorsize_str); 3938f8de1e1SXin LI 3948f8de1e1SXin LI free(ops); 3958f8de1e1SXin LI return (args); 3968f8de1e1SXin LI } 3978f8de1e1SXin LI 3988f8de1e1SXin LI static const char * 3998f8de1e1SXin LI swap_on_off_geli(const char *name, char *mntops, int doingall) 4008f8de1e1SXin LI { 4018f8de1e1SXin LI struct stat sb; 40279ba2f31SHiroki Sato char *dname, *args; 4038f8de1e1SXin LI int error; 4048f8de1e1SXin LI 4058f8de1e1SXin LI error = stat(name, &sb); 4068f8de1e1SXin LI 4078f8de1e1SXin LI if (which_prog == SWAPON) do { 40879ba2f31SHiroki Sato /* Skip if the .eli device already exists. */ 4098f8de1e1SXin LI if (error == 0) 4108f8de1e1SXin LI break; 4118f8de1e1SXin LI 4128f8de1e1SXin LI args = swap_on_geli_args(mntops); 4138f8de1e1SXin LI if (args == NULL) 4148f8de1e1SXin LI return (NULL); 4158f8de1e1SXin LI 4168f8de1e1SXin LI dname = swap_basename(name); 4178f8de1e1SXin LI if (dname == NULL) { 4188f8de1e1SXin LI free(args); 4198f8de1e1SXin LI return (NULL); 4208f8de1e1SXin LI } 4218f8de1e1SXin LI 4228f8de1e1SXin LI error = run_cmd(NULL, "%s onetime%s %s", _PATH_GELI, args, 423cb754f61SHiroki Sato dname); 4248f8de1e1SXin LI 4258f8de1e1SXin LI free(dname); 4268f8de1e1SXin LI free(args); 4278f8de1e1SXin LI 428268a55bcSHiroki Sato if (error) { 42979ba2f31SHiroki Sato /* error occured during creation. */ 43079ba2f31SHiroki Sato if (qflag == 0) 4318f8de1e1SXin LI warnx("%s: Invalid parameters", name); 432268a55bcSHiroki Sato return (NULL); 433268a55bcSHiroki Sato } 4348f8de1e1SXin LI } while (0); 435268a55bcSHiroki Sato 436268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 437268a55bcSHiroki Sato } 438268a55bcSHiroki Sato 439268a55bcSHiroki Sato static const char * 4408f8de1e1SXin LI swap_on_off_md(const char *name, char *mntops, int doingall) 441268a55bcSHiroki Sato { 442268a55bcSHiroki Sato FILE *sfd; 443268a55bcSHiroki Sato int fd, mdunit, error; 444268a55bcSHiroki Sato const char *ret; 44554282733SXin LI static char mdpath[PATH_MAX], linebuf[PATH_MAX]; 446268a55bcSHiroki Sato char *p, *vnodefile; 447268a55bcSHiroki Sato size_t linelen; 448268a55bcSHiroki Sato u_long ul; 449268a55bcSHiroki Sato 450268a55bcSHiroki Sato fd = -1; 451268a55bcSHiroki Sato sfd = NULL; 452268a55bcSHiroki Sato if (strlen(name) == (sizeof(MD_NAME) - 1)) 453268a55bcSHiroki Sato mdunit = -1; 454268a55bcSHiroki Sato else { 455268a55bcSHiroki Sato errno = 0; 456268a55bcSHiroki Sato ul = strtoul(name + 2, &p, 10); 457268a55bcSHiroki Sato if (errno == 0) { 458268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 459268a55bcSHiroki Sato errno = EINVAL; 460268a55bcSHiroki Sato } 461268a55bcSHiroki Sato if (errno) { 462268a55bcSHiroki Sato warn("Bad device unit: %s", name); 463268a55bcSHiroki Sato return (NULL); 464268a55bcSHiroki Sato } 465268a55bcSHiroki Sato mdunit = (int)ul; 466268a55bcSHiroki Sato } 467268a55bcSHiroki Sato 468268a55bcSHiroki Sato vnodefile = NULL; 469268a55bcSHiroki Sato if ((p = strstr(mntops, "file=")) != NULL) { 470268a55bcSHiroki Sato vnodefile = strdup(p + sizeof("file=") - 1); 471268a55bcSHiroki Sato p = strchr(vnodefile, ','); 472268a55bcSHiroki Sato if (p != NULL) 473268a55bcSHiroki Sato *p = '\0'; 474268a55bcSHiroki Sato } 475268a55bcSHiroki Sato if (vnodefile == NULL) { 476268a55bcSHiroki Sato warnx("file option not found for %s", name); 477268a55bcSHiroki Sato return (NULL); 478268a55bcSHiroki Sato } 479268a55bcSHiroki Sato 4808f8de1e1SXin LI if (which_prog == SWAPON) { 481268a55bcSHiroki Sato if (mdunit == -1) { 482268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 483268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 484268a55bcSHiroki Sato if (error == 0) { 485268a55bcSHiroki Sato /* md device found. Ignore it. */ 486268a55bcSHiroki Sato close(fd); 487268a55bcSHiroki Sato if (!qflag) 488268a55bcSHiroki Sato warnx("%s: Device already in use", 489268a55bcSHiroki Sato vnodefile); 4901bf9e66cSXin LI free(vnodefile); 491268a55bcSHiroki Sato return (NULL); 492268a55bcSHiroki Sato } 493268a55bcSHiroki Sato error = run_cmd(&fd, "%s -a -t vnode -n -f %s", 494268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 495268a55bcSHiroki Sato if (error) { 496268a55bcSHiroki Sato warnx("mdconfig (attach) error: file=%s", 497268a55bcSHiroki Sato vnodefile); 4981bf9e66cSXin LI free(vnodefile); 499268a55bcSHiroki Sato return (NULL); 500268a55bcSHiroki Sato } 501268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 502268a55bcSHiroki Sato if (sfd == NULL) { 503268a55bcSHiroki Sato warn("mdconfig (attach) fdopen error"); 504268a55bcSHiroki Sato ret = NULL; 505268a55bcSHiroki Sato goto err; 506268a55bcSHiroki Sato } 507268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 508268a55bcSHiroki Sato if (p == NULL && 509268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf))) { 510268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output"); 511268a55bcSHiroki Sato ret = NULL; 512268a55bcSHiroki Sato goto err; 513268a55bcSHiroki Sato } 514268a55bcSHiroki Sato strncpy(linebuf, p, linelen); 515268a55bcSHiroki Sato linebuf[linelen - 1] = '\0'; 516268a55bcSHiroki Sato errno = 0; 517268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 518268a55bcSHiroki Sato if (errno == 0) { 519268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 520268a55bcSHiroki Sato errno = EINVAL; 521268a55bcSHiroki Sato } 522268a55bcSHiroki Sato if (errno) { 523268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output: %s", 524268a55bcSHiroki Sato linebuf); 525268a55bcSHiroki Sato ret = NULL; 526268a55bcSHiroki Sato goto err; 527268a55bcSHiroki Sato } 528268a55bcSHiroki Sato mdunit = (int)ul; 529268a55bcSHiroki Sato } else { 530268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 531268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 532268a55bcSHiroki Sato if (error == 0) { 533268a55bcSHiroki Sato /* md device found. Ignore it. */ 534268a55bcSHiroki Sato close(fd); 53579ba2f31SHiroki Sato if (qflag == 0) 536268a55bcSHiroki Sato warnx("md%d on %s: Device already " 537268a55bcSHiroki Sato "in use", mdunit, vnodefile); 5381bf9e66cSXin LI free(vnodefile); 539268a55bcSHiroki Sato return (NULL); 540268a55bcSHiroki Sato } 541268a55bcSHiroki Sato error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", 542268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit, vnodefile); 543268a55bcSHiroki Sato if (error) { 544268a55bcSHiroki Sato warnx("mdconfig (attach) error: " 545268a55bcSHiroki Sato "md%d on file=%s", mdunit, vnodefile); 5461bf9e66cSXin LI free(vnodefile); 547268a55bcSHiroki Sato return (NULL); 548268a55bcSHiroki Sato } 549268a55bcSHiroki Sato } 5508f8de1e1SXin LI } else /* SWAPOFF */ { 551268a55bcSHiroki Sato if (mdunit == -1) { 552268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 553268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 554268a55bcSHiroki Sato if (error) { 555268a55bcSHiroki Sato /* md device not found. Ignore it. */ 556268a55bcSHiroki Sato close(fd); 557268a55bcSHiroki Sato if (!qflag) 558268a55bcSHiroki Sato warnx("md on %s: Device not found", 559268a55bcSHiroki Sato vnodefile); 5601bf9e66cSXin LI free(vnodefile); 561268a55bcSHiroki Sato return (NULL); 562268a55bcSHiroki Sato } 563268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 564268a55bcSHiroki Sato if (sfd == NULL) { 565268a55bcSHiroki Sato warn("mdconfig (list) fdopen error"); 566268a55bcSHiroki Sato ret = NULL; 567268a55bcSHiroki Sato goto err; 568268a55bcSHiroki Sato } 569268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 570268a55bcSHiroki Sato if (p == NULL && 571268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf) - 1)) { 572268a55bcSHiroki Sato warn("mdconfig (list) unexpected output"); 573268a55bcSHiroki Sato ret = NULL; 574268a55bcSHiroki Sato goto err; 575268a55bcSHiroki Sato } 576268a55bcSHiroki Sato strncpy(linebuf, p, linelen); 577268a55bcSHiroki Sato linebuf[linelen - 1] = '\0'; 578268a55bcSHiroki Sato p = strchr(linebuf, ' '); 579268a55bcSHiroki Sato if (p != NULL) 580268a55bcSHiroki Sato *p = '\0'; 581268a55bcSHiroki Sato errno = 0; 582268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 583268a55bcSHiroki Sato if (errno == 0) { 584268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 585268a55bcSHiroki Sato errno = EINVAL; 586268a55bcSHiroki Sato } 587268a55bcSHiroki Sato if (errno) { 588268a55bcSHiroki Sato warn("mdconfig (list) unexpected output: %s", 589268a55bcSHiroki Sato linebuf); 590268a55bcSHiroki Sato ret = NULL; 591268a55bcSHiroki Sato goto err; 592268a55bcSHiroki Sato } 593268a55bcSHiroki Sato mdunit = (int)ul; 594268a55bcSHiroki Sato } else { 595268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 596268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 597268a55bcSHiroki Sato if (error) { 598268a55bcSHiroki Sato /* md device not found. Ignore it. */ 599268a55bcSHiroki Sato close(fd); 600268a55bcSHiroki Sato if (!qflag) 601268a55bcSHiroki Sato warnx("md%d on %s: Device not found", 602268a55bcSHiroki Sato mdunit, vnodefile); 6031bf9e66cSXin LI free(vnodefile); 604268a55bcSHiroki Sato return (NULL); 605268a55bcSHiroki Sato } 606268a55bcSHiroki Sato } 607268a55bcSHiroki Sato } 608268a55bcSHiroki Sato snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, 609268a55bcSHiroki Sato MD_NAME, mdunit); 610268a55bcSHiroki Sato mdpath[sizeof(mdpath) - 1] = '\0'; 611268a55bcSHiroki Sato ret = swap_on_off_sfile(mdpath, doingall); 612268a55bcSHiroki Sato 6138f8de1e1SXin LI if (which_prog == SWAPOFF) { 614268a55bcSHiroki Sato if (ret != NULL) { 615268a55bcSHiroki Sato error = run_cmd(NULL, "%s -d -u %d", 616268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit); 617268a55bcSHiroki Sato if (error) 618268a55bcSHiroki Sato warn("mdconfig (detach) detach failed: %s%s%d", 619268a55bcSHiroki Sato _PATH_DEV, MD_NAME, mdunit); 620268a55bcSHiroki Sato } 621268a55bcSHiroki Sato } 622268a55bcSHiroki Sato err: 623268a55bcSHiroki Sato if (sfd != NULL) 624268a55bcSHiroki Sato fclose(sfd); 625268a55bcSHiroki Sato if (fd != -1) 626268a55bcSHiroki Sato close(fd); 6271bf9e66cSXin LI free(vnodefile); 628268a55bcSHiroki Sato return (ret); 629268a55bcSHiroki Sato } 630268a55bcSHiroki Sato 631268a55bcSHiroki Sato static int 632268a55bcSHiroki Sato run_cmd(int *ofd, const char *cmdline, ...) 633268a55bcSHiroki Sato { 634268a55bcSHiroki Sato va_list ap; 635268a55bcSHiroki Sato char **argv, **argvp, *cmd, *p; 636268a55bcSHiroki Sato int argc, pid, status, rv; 637268a55bcSHiroki Sato int pfd[2], nfd, dup2dn; 638268a55bcSHiroki Sato 639268a55bcSHiroki Sato va_start(ap, cmdline); 640268a55bcSHiroki Sato rv = vasprintf(&cmd, cmdline, ap); 641268a55bcSHiroki Sato if (rv == -1) { 642268a55bcSHiroki Sato warn("%s", __func__); 643268a55bcSHiroki Sato return (rv); 644268a55bcSHiroki Sato } 645268a55bcSHiroki Sato va_end(ap); 646268a55bcSHiroki Sato 647268a55bcSHiroki Sato for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 648268a55bcSHiroki Sato argc++; 649268a55bcSHiroki Sato argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 650268a55bcSHiroki Sato for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 651268a55bcSHiroki Sato if (**argvp != '\0' && (++argvp > &argv[argc])) { 652268a55bcSHiroki Sato *argvp = NULL; 653268a55bcSHiroki Sato break; 654268a55bcSHiroki Sato } 655268a55bcSHiroki Sato /* The argv array ends up NULL-terminated here. */ 656268a55bcSHiroki Sato #if 0 657268a55bcSHiroki Sato { 658268a55bcSHiroki Sato int i; 659268a55bcSHiroki Sato 660268a55bcSHiroki Sato fprintf(stderr, "DEBUG: running:"); 661268a55bcSHiroki Sato /* Should be equivalent to 'cmd' (before strsep, of course). */ 662268a55bcSHiroki Sato for (i = 0; argv[i] != NULL; i++) 663268a55bcSHiroki Sato fprintf(stderr, " %s", argv[i]); 664268a55bcSHiroki Sato fprintf(stderr, "\n"); 665268a55bcSHiroki Sato } 666268a55bcSHiroki Sato #endif 667268a55bcSHiroki Sato dup2dn = 1; 668268a55bcSHiroki Sato if (ofd != NULL) { 669268a55bcSHiroki Sato if (pipe(&pfd[0]) == -1) { 670268a55bcSHiroki Sato warn("%s: pipe", __func__); 671268a55bcSHiroki Sato return (-1); 672268a55bcSHiroki Sato } 673268a55bcSHiroki Sato *ofd = pfd[0]; 674268a55bcSHiroki Sato dup2dn = 0; 675268a55bcSHiroki Sato } 676268a55bcSHiroki Sato pid = fork(); 677268a55bcSHiroki Sato switch (pid) { 678268a55bcSHiroki Sato case 0: 679268a55bcSHiroki Sato /* Child process. */ 680268a55bcSHiroki Sato if (ofd != NULL) 681268a55bcSHiroki Sato if (dup2(pfd[1], STDOUT_FILENO) < 0) 682268a55bcSHiroki Sato err(1, "dup2 in %s", __func__); 683268a55bcSHiroki Sato nfd = open(_PATH_DEVNULL, O_RDWR); 684268a55bcSHiroki Sato if (nfd == -1) 685268a55bcSHiroki Sato err(1, "%s: open %s", __func__, _PATH_DEVNULL); 686268a55bcSHiroki Sato if (dup2(nfd, STDIN_FILENO) < 0) 687268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 688268a55bcSHiroki Sato if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0) 689268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 690268a55bcSHiroki Sato if (dup2(nfd, STDERR_FILENO) < 0) 691268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 692268a55bcSHiroki Sato execv(argv[0], argv); 693268a55bcSHiroki Sato warn("exec: %s", argv[0]); 694268a55bcSHiroki Sato _exit(-1); 695268a55bcSHiroki Sato case -1: 696268a55bcSHiroki Sato err(1, "%s: fork", __func__); 697268a55bcSHiroki Sato } 698268a55bcSHiroki Sato free(cmd); 699268a55bcSHiroki Sato free(argv); 700268a55bcSHiroki Sato while (waitpid(pid, &status, 0) != pid) 701268a55bcSHiroki Sato ; 702268a55bcSHiroki Sato return (WEXITSTATUS(status)); 703268a55bcSHiroki Sato } 704268a55bcSHiroki Sato 705268a55bcSHiroki Sato static const char * 7068f8de1e1SXin LI swap_on_off_sfile(const char *name, int doingall) 707268a55bcSHiroki Sato { 708268a55bcSHiroki Sato int error; 709268a55bcSHiroki Sato 7108f8de1e1SXin LI if (which_prog == SWAPON) 711268a55bcSHiroki Sato error = swapon(name); 7128f8de1e1SXin LI else /* SWAPOFF */ 713268a55bcSHiroki Sato error = swapoff(name); 7148f8de1e1SXin LI 715268a55bcSHiroki Sato if (error == -1) { 7168fae3551SRodney W. Grimes switch (errno) { 7178fae3551SRodney W. Grimes case EBUSY: 71879ba2f31SHiroki Sato if (doingall == 0) 719268a55bcSHiroki Sato warnx("%s: Device already in use", name); 7208fae3551SRodney W. Grimes break; 7214937798dSDavid Schultz case EINVAL: 7224937798dSDavid Schultz if (which_prog == SWAPON) 7234937798dSDavid Schultz warnx("%s: NSWAPDEV limit reached", name); 72479ba2f31SHiroki Sato else if (doingall == 0) 7254937798dSDavid Schultz warn("%s", name); 7264937798dSDavid Schultz break; 7278fae3551SRodney W. Grimes default: 7286da7f378SPhilippe Charnier warn("%s", name); 7298fae3551SRodney W. Grimes break; 7308fae3551SRodney W. Grimes } 731268a55bcSHiroki Sato return (NULL); 7328fae3551SRodney W. Grimes } 733268a55bcSHiroki Sato return (name); 7348fae3551SRodney W. Grimes } 7358fae3551SRodney W. Grimes 7366da7f378SPhilippe Charnier static void 737a420c811SMatthew Dillon usage(void) 7388fae3551SRodney W. Grimes { 73979ba2f31SHiroki Sato 740a420c811SMatthew Dillon fprintf(stderr, "usage: %s ", getprogname()); 741a420c811SMatthew Dillon switch(orig_prog) { 742a420c811SMatthew Dillon case SWAPON: 7438d646af5SRuslan Ermilov case SWAPOFF: 744268a55bcSHiroki Sato fprintf(stderr, "[-F fstab] -aLq | file ...\n"); 745a420c811SMatthew Dillon break; 746a420c811SMatthew Dillon case SWAPCTL: 7472e64768cSPawel Jakub Dawidek fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 748a420c811SMatthew Dillon break; 749a420c811SMatthew Dillon } 7508fae3551SRodney W. Grimes exit(1); 7518fae3551SRodney W. Grimes } 75292da00bbSMatthew Dillon 753a420c811SMatthew Dillon static void 7542e64768cSPawel Jakub Dawidek sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 7552e64768cSPawel Jakub Dawidek long blocksize) 7562e64768cSPawel Jakub Dawidek { 7572e64768cSPawel Jakub Dawidek char tmp[16]; 7582e64768cSPawel Jakub Dawidek 75979ba2f31SHiroki Sato if (hflag == 'H') { 7602e64768cSPawel Jakub Dawidek humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 7612e64768cSPawel Jakub Dawidek HN_B | HN_NOSPACE | HN_DECIMAL); 7622e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*s", hlen, tmp); 76379ba2f31SHiroki Sato } else 7642e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 7652e64768cSPawel Jakub Dawidek } 7662e64768cSPawel Jakub Dawidek 7672e64768cSPawel Jakub Dawidek static void 768a420c811SMatthew Dillon swaplist(int lflag, int sflag, int hflag) 76992da00bbSMatthew Dillon { 770a420c811SMatthew Dillon size_t mibsize, size; 771a420c811SMatthew Dillon struct xswdev xsw; 77269095b02SMike Barcroft int hlen, mib[16], n, pagesize; 773a420c811SMatthew Dillon long blocksize; 774a420c811SMatthew Dillon long long total = 0; 775a420c811SMatthew Dillon long long used = 0; 776a420c811SMatthew Dillon long long tmp_total; 777a420c811SMatthew Dillon long long tmp_used; 7782e64768cSPawel Jakub Dawidek char buf[32]; 77992da00bbSMatthew Dillon 780a420c811SMatthew Dillon pagesize = getpagesize(); 781a420c811SMatthew Dillon switch(hflag) { 7822e64768cSPawel Jakub Dawidek case 'G': 7832e64768cSPawel Jakub Dawidek blocksize = 1024 * 1024 * 1024; 7842e64768cSPawel Jakub Dawidek strlcpy(buf, "1GB-blocks", sizeof(buf)); 7852e64768cSPawel Jakub Dawidek hlen = 10; 7862e64768cSPawel Jakub Dawidek break; 7872e64768cSPawel Jakub Dawidek case 'H': 7882e64768cSPawel Jakub Dawidek blocksize = -1; 7892e64768cSPawel Jakub Dawidek strlcpy(buf, "Bytes", sizeof(buf)); 7902e64768cSPawel Jakub Dawidek hlen = 10; 7912e64768cSPawel Jakub Dawidek break; 792a420c811SMatthew Dillon case 'K': 793a420c811SMatthew Dillon blocksize = 1024; 7942e64768cSPawel Jakub Dawidek strlcpy(buf, "1kB-blocks", sizeof(buf)); 795a420c811SMatthew Dillon hlen = 10; 796a420c811SMatthew Dillon break; 797a420c811SMatthew Dillon case 'M': 798a420c811SMatthew Dillon blocksize = 1024 * 1024; 7992e64768cSPawel Jakub Dawidek strlcpy(buf, "1MB-blocks", sizeof(buf)); 800a420c811SMatthew Dillon hlen = 10; 801a420c811SMatthew Dillon break; 802a420c811SMatthew Dillon default: 8039255f327SMike Barcroft getbsize(&hlen, &blocksize); 8042e64768cSPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 805a420c811SMatthew Dillon break; 80692da00bbSMatthew Dillon } 807a420c811SMatthew Dillon 80879ba2f31SHiroki Sato mibsize = nitems(mib); 809a420c811SMatthew Dillon if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 810a420c811SMatthew Dillon err(1, "sysctlnametomib()"); 811a420c811SMatthew Dillon 812a420c811SMatthew Dillon if (lflag) { 813a420c811SMatthew Dillon printf("%-13s %*s %*s\n", 814a420c811SMatthew Dillon "Device:", 815a420c811SMatthew Dillon hlen, buf, 816a420c811SMatthew Dillon hlen, "Used:"); 817a420c811SMatthew Dillon } 818a420c811SMatthew Dillon 819a420c811SMatthew Dillon for (n = 0; ; ++n) { 820a420c811SMatthew Dillon mib[mibsize] = n; 821a420c811SMatthew Dillon size = sizeof xsw; 82216fc3635SMark Murray if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 823a420c811SMatthew Dillon break; 824a420c811SMatthew Dillon if (xsw.xsw_version != XSWDEV_VERSION) 825a420c811SMatthew Dillon errx(1, "xswdev version mismatch"); 826a420c811SMatthew Dillon 8272e64768cSPawel Jakub Dawidek tmp_total = (long long)xsw.xsw_nblks * pagesize; 8282e64768cSPawel Jakub Dawidek tmp_used = (long long)xsw.xsw_used * pagesize; 829a420c811SMatthew Dillon total += tmp_total; 830a420c811SMatthew Dillon used += tmp_used; 831a420c811SMatthew Dillon if (lflag) { 8322e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 8332e64768cSPawel Jakub Dawidek blocksize); 8342e64768cSPawel Jakub Dawidek printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 8352e64768cSPawel Jakub Dawidek buf); 8362e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 8372e64768cSPawel Jakub Dawidek blocksize); 8382e64768cSPawel Jakub Dawidek printf("%s\n", buf); 839a420c811SMatthew Dillon } 840a420c811SMatthew Dillon } 841a420c811SMatthew Dillon if (errno != ENOENT) 842a420c811SMatthew Dillon err(1, "sysctl()"); 843a420c811SMatthew Dillon 844a420c811SMatthew Dillon if (sflag) { 8452e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 8462e64768cSPawel Jakub Dawidek printf("Total: %s ", buf); 8472e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 8482e64768cSPawel Jakub Dawidek printf("%s\n", buf); 849a420c811SMatthew Dillon } 850a420c811SMatthew Dillon } 851a420c811SMatthew Dillon 852