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 32c69284caSDavid E. O'Brien #if 0 338fae3551SRodney W. Grimes #ifndef lint 34e798a806SPhilippe Charnier static const char copyright[] = 358fae3551SRodney W. Grimes "@(#) Copyright (c) 1980, 1993\n\ 368fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 378fae3551SRodney W. Grimes #endif /* not lint */ 388fae3551SRodney W. Grimes 398fae3551SRodney W. Grimes #ifndef lint 408fae3551SRodney W. Grimes static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93"; 418fae3551SRodney W. Grimes #endif /* not lint */ 42c69284caSDavid E. O'Brien #endif 43c69284caSDavid E. O'Brien #include <sys/cdefs.h> 44c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 458fae3551SRodney W. Grimes 46a420c811SMatthew Dillon #include <sys/param.h> 479035b225SDoug Moore #include <sys/disk.h> 48504f5e29SDoug Moore #include <sys/disklabel.h> 49268a55bcSHiroki Sato #include <sys/mdioctl.h> 50268a55bcSHiroki Sato #include <sys/stat.h> 51a420c811SMatthew Dillon #include <sys/sysctl.h> 52268a55bcSHiroki Sato #include <sys/wait.h> 536004362eSDavid Schultz #include <vm/vm_param.h> 541aa249c9SKonstantin Belousov #include <vm/swap_pager.h> 55a420c811SMatthew Dillon 566da7f378SPhilippe Charnier #include <err.h> 57e798a806SPhilippe Charnier #include <errno.h> 58268a55bcSHiroki Sato #include <fcntl.h> 59268a55bcSHiroki Sato #include <fnmatch.h> 60e798a806SPhilippe Charnier #include <fstab.h> 61268a55bcSHiroki Sato #include <libgen.h> 62268a55bcSHiroki Sato #include <libutil.h> 63268a55bcSHiroki Sato #include <limits.h> 64268a55bcSHiroki Sato #include <paths.h> 65268a55bcSHiroki Sato #include <stdarg.h> 66e798a806SPhilippe Charnier #include <stdio.h> 67cafefe8cSDima Dorfman #include <stdlib.h> 68e798a806SPhilippe Charnier #include <string.h> 69e798a806SPhilippe Charnier #include <unistd.h> 708fae3551SRodney W. Grimes 71*65f3be91SAlfonso Gregory static void usage(void) __dead2; 728f8de1e1SXin LI static const char *swap_on_off(const char *, int, char *); 738f8de1e1SXin LI static const char *swap_on_off_gbde(const char *, int); 748f8de1e1SXin LI static const char *swap_on_off_geli(const char *, char *, int); 758f8de1e1SXin LI static const char *swap_on_off_md(const char *, char *, int); 768f8de1e1SXin LI static const char *swap_on_off_sfile(const char *, int); 77a420c811SMatthew Dillon static void swaplist(int, int, int); 78268a55bcSHiroki Sato static int run_cmd(int *, const char *, ...) __printflike(2, 3); 79a420c811SMatthew Dillon 801efe3c6bSEd Schouten static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 8138994f93SPoul-Henning Kamp 821aa249c9SKonstantin Belousov static int Eflag, fflag, qflag; 83268a55bcSHiroki Sato 8438994f93SPoul-Henning Kamp int 8538994f93SPoul-Henning Kamp main(int argc, char **argv) 868fae3551SRodney W. Grimes { 873d438ad6SDavid E. O'Brien struct fstab *fsp; 88268a55bcSHiroki Sato const char *swfile; 89a420c811SMatthew Dillon char *ptr; 9079ba2f31SHiroki Sato int ret, ch, doall; 9179ba2f31SHiroki Sato int sflag, lflag, late, hflag; 92633d2bc5SMaxim Sobolev const char *etc_fstab; 9392da00bbSMatthew Dillon 9479ba2f31SHiroki Sato sflag = lflag = late = hflag = 0; 95a420c811SMatthew Dillon if ((ptr = strrchr(argv[0], '/')) == NULL) 96a420c811SMatthew Dillon ptr = argv[0]; 9779ba2f31SHiroki Sato if (strstr(ptr, "swapon") != NULL) 98a420c811SMatthew Dillon which_prog = SWAPON; 9979ba2f31SHiroki Sato else if (strstr(ptr, "swapoff") != NULL) 100a420c811SMatthew Dillon which_prog = SWAPOFF; 101a420c811SMatthew Dillon orig_prog = which_prog; 1028fae3551SRodney W. Grimes 1038fae3551SRodney W. Grimes doall = 0; 104633d2bc5SMaxim Sobolev etc_fstab = NULL; 1051aa249c9SKonstantin Belousov while ((ch = getopt(argc, argv, "AadEfghklLmqsUF:")) != -1) { 106a420c811SMatthew Dillon switch(ch) { 107a420c811SMatthew Dillon case 'A': 108a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 1098fae3551SRodney W. Grimes doall = 1; 110a420c811SMatthew Dillon which_prog = SWAPON; 11179ba2f31SHiroki Sato } else 112a420c811SMatthew Dillon usage(); 113a420c811SMatthew Dillon break; 114a420c811SMatthew Dillon case 'a': 115a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) 116a420c811SMatthew Dillon doall = 1; 117a420c811SMatthew Dillon else 118a420c811SMatthew Dillon which_prog = SWAPON; 119a420c811SMatthew Dillon break; 120a420c811SMatthew Dillon case 'd': 121a420c811SMatthew Dillon if (which_prog == SWAPCTL) 122a420c811SMatthew Dillon which_prog = SWAPOFF; 123a420c811SMatthew Dillon else 124a420c811SMatthew Dillon usage(); 125a420c811SMatthew Dillon break; 126a616b253SDoug Moore case 'E': 127a616b253SDoug Moore if (which_prog == SWAPON) 128a616b253SDoug Moore Eflag = 2; 129a616b253SDoug Moore else 130a616b253SDoug Moore usage(); 131a616b253SDoug Moore break; 1321aa249c9SKonstantin Belousov case 'f': 1331aa249c9SKonstantin Belousov if (which_prog == SWAPOFF) 1341aa249c9SKonstantin Belousov fflag = 1; 1351aa249c9SKonstantin Belousov else 1361aa249c9SKonstantin Belousov usage(); 1371aa249c9SKonstantin Belousov break; 1382e64768cSPawel Jakub Dawidek case 'g': 1392e64768cSPawel Jakub Dawidek hflag = 'G'; 1402e64768cSPawel Jakub Dawidek break; 1412e64768cSPawel Jakub Dawidek case 'h': 1422e64768cSPawel Jakub Dawidek hflag = 'H'; 1432e64768cSPawel Jakub Dawidek break; 1442e64768cSPawel Jakub Dawidek case 'k': 1452e64768cSPawel Jakub Dawidek hflag = 'K'; 146a420c811SMatthew Dillon break; 147a420c811SMatthew Dillon case 'l': 148a420c811SMatthew Dillon lflag = 1; 149a420c811SMatthew Dillon break; 150268a55bcSHiroki Sato case 'L': 151268a55bcSHiroki Sato late = 1; 152268a55bcSHiroki Sato break; 1532e64768cSPawel Jakub Dawidek case 'm': 154a420c811SMatthew Dillon hflag = 'M'; 155a420c811SMatthew Dillon break; 15645a5dc93SMike Makonnen case 'q': 15745a5dc93SMike Makonnen if (which_prog == SWAPON || which_prog == SWAPOFF) 15845a5dc93SMike Makonnen qflag = 1; 15945a5dc93SMike Makonnen break; 1602e64768cSPawel Jakub Dawidek case 's': 1612e64768cSPawel Jakub Dawidek sflag = 1; 162a420c811SMatthew Dillon break; 163a420c811SMatthew Dillon case 'U': 164a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 165a420c811SMatthew Dillon doall = 1; 166a420c811SMatthew Dillon which_prog = SWAPOFF; 16779ba2f31SHiroki Sato } else 168a420c811SMatthew Dillon usage(); 1698fae3551SRodney W. Grimes break; 170633d2bc5SMaxim Sobolev case 'F': 171633d2bc5SMaxim Sobolev etc_fstab = optarg; 172633d2bc5SMaxim Sobolev break; 1738fae3551SRodney W. Grimes case '?': 1748fae3551SRodney W. Grimes default: 175a420c811SMatthew Dillon usage(); 176a420c811SMatthew Dillon } 1778fae3551SRodney W. Grimes } 1788fae3551SRodney W. Grimes argv += optind; 1798fae3551SRodney W. Grimes 180ce458f42SEd Schouten ret = 0; 181268a55bcSHiroki Sato swfile = NULL; 182633d2bc5SMaxim Sobolev if (etc_fstab != NULL) 183633d2bc5SMaxim Sobolev setfstab(etc_fstab); 184a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) { 185a420c811SMatthew Dillon if (doall) { 18638994f93SPoul-Henning Kamp while ((fsp = getfsent()) != NULL) { 1874139627dSHiroki Sato if (strcmp(fsp->fs_type, FSTAB_SW) != 0) 1888fae3551SRodney W. Grimes continue; 1894139627dSHiroki Sato if (strstr(fsp->fs_mntops, "noauto") != NULL) 1907fc4a454SJordan K. Hubbard continue; 191268a55bcSHiroki Sato if (which_prog != SWAPOFF && 1921482f982SHiroki Sato strstr(fsp->fs_mntops, "late") && 1934139627dSHiroki Sato late == 0) 194268a55bcSHiroki Sato continue; 1957627b330SJilles Tjoelker if (which_prog == SWAPOFF && 1967627b330SJilles Tjoelker strstr(fsp->fs_mntops, "late") == NULL && 1977627b330SJilles Tjoelker late != 0) 1987627b330SJilles Tjoelker continue; 199a616b253SDoug Moore Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL); 200268a55bcSHiroki Sato swfile = swap_on_off(fsp->fs_spec, 1, 201268a55bcSHiroki Sato fsp->fs_mntops); 202a616b253SDoug Moore Eflag &= ~1; 203268a55bcSHiroki Sato if (swfile == NULL) { 204ce458f42SEd Schouten ret = 1; 205268a55bcSHiroki Sato continue; 206268a55bcSHiroki Sato } 20779ba2f31SHiroki Sato if (qflag == 0) { 20892da00bbSMatthew Dillon printf("%s: %sing %s as swap device\n", 20945a5dc93SMike Makonnen getprogname(), 210268a55bcSHiroki Sato (which_prog == SWAPOFF) ? 211268a55bcSHiroki Sato "remov" : "add", swfile); 212a420c811SMatthew Dillon } 213a420c811SMatthew Dillon } 21479ba2f31SHiroki Sato } else if (*argv == NULL) 215a420c811SMatthew Dillon usage(); 216a420c811SMatthew Dillon for (; *argv; ++argv) { 217268a55bcSHiroki Sato swfile = swap_on_off(*argv, 0, NULL); 218268a55bcSHiroki Sato if (swfile == NULL) { 219ce458f42SEd Schouten ret = 1; 220268a55bcSHiroki Sato continue; 221268a55bcSHiroki Sato } 222268a55bcSHiroki Sato if (orig_prog == SWAPCTL) { 223a420c811SMatthew Dillon printf("%s: %sing %s as swap device\n", 224268a55bcSHiroki Sato getprogname(), 225268a55bcSHiroki Sato (which_prog == SWAPOFF) ? "remov" : "add", 226268a55bcSHiroki Sato swfile); 227a420c811SMatthew Dillon } 228a420c811SMatthew Dillon } 229a420c811SMatthew Dillon } else { 230a420c811SMatthew Dillon if (lflag || sflag) 231a420c811SMatthew Dillon swaplist(lflag, sflag, hflag); 232a420c811SMatthew Dillon else 233a420c811SMatthew Dillon usage(); 234a420c811SMatthew Dillon } 235ce458f42SEd Schouten exit(ret); 2368fae3551SRodney W. Grimes } 2378fae3551SRodney W. Grimes 238268a55bcSHiroki Sato static const char * 2398f8de1e1SXin LI swap_on_off(const char *name, int doingall, char *mntops) 2408fae3551SRodney W. Grimes { 241e47c947eSEd Schouten char *base, *basebuf; 242268a55bcSHiroki Sato 243268a55bcSHiroki Sato /* Swap on vnode-backed md(4) device. */ 244268a55bcSHiroki Sato if (mntops != NULL && 2458f8de1e1SXin LI (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || 2468f8de1e1SXin LI fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || 247268a55bcSHiroki Sato strncmp(_PATH_DEV MD_NAME, name, 248268a55bcSHiroki Sato sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || 249268a55bcSHiroki Sato strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) 250268a55bcSHiroki Sato return (swap_on_off_md(name, mntops, doingall)); 251268a55bcSHiroki Sato 252e47c947eSEd Schouten basebuf = strdup(name); 253e47c947eSEd Schouten base = basename(basebuf); 2548f8de1e1SXin LI 2558f8de1e1SXin LI /* Swap on encrypted device by GEOM_BDE. */ 256e47c947eSEd Schouten if (fnmatch("*.bde", base, 0) == 0) { 257e47c947eSEd Schouten free(basebuf); 258268a55bcSHiroki Sato return (swap_on_off_gbde(name, doingall)); 259e47c947eSEd Schouten } 260268a55bcSHiroki Sato 261268a55bcSHiroki Sato /* Swap on encrypted device by GEOM_ELI. */ 262e47c947eSEd Schouten if (fnmatch("*.eli", base, 0) == 0) { 263e47c947eSEd Schouten free(basebuf); 264268a55bcSHiroki Sato return (swap_on_off_geli(name, mntops, doingall)); 265e47c947eSEd Schouten } 266268a55bcSHiroki Sato 267268a55bcSHiroki Sato /* Swap on special file. */ 268e47c947eSEd Schouten free(basebuf); 269268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 270268a55bcSHiroki Sato } 271268a55bcSHiroki Sato 2728f8de1e1SXin LI /* Strip off .bde or .eli suffix from swap device name */ 2738f8de1e1SXin LI static char * 2748f8de1e1SXin LI swap_basename(const char *name) 275268a55bcSHiroki Sato { 276cb754f61SHiroki Sato char *dname, *p; 277268a55bcSHiroki Sato 278cb754f61SHiroki Sato dname = strdup(name); 279cb754f61SHiroki Sato p = strrchr(dname, '.'); 2808f8de1e1SXin LI /* assert(p != NULL); */ 281268a55bcSHiroki Sato *p = '\0'; 282268a55bcSHiroki Sato 2838f8de1e1SXin LI return (dname); 2848f8de1e1SXin LI } 2858f8de1e1SXin LI 2868f8de1e1SXin LI static const char * 2878f8de1e1SXin LI swap_on_off_gbde(const char *name, int doingall) 2888f8de1e1SXin LI { 2898f8de1e1SXin LI const char *ret; 2901fdb18b0SJilles Tjoelker char pass[64 * 2 + 1]; 2911fdb18b0SJilles Tjoelker unsigned char bpass[64]; 2928f8de1e1SXin LI char *dname; 2938f8de1e1SXin LI int i, error; 2948f8de1e1SXin LI 2958f8de1e1SXin LI dname = swap_basename(name); 2968f8de1e1SXin LI if (dname == NULL) 2978f8de1e1SXin LI return (NULL); 2988f8de1e1SXin LI 2998f8de1e1SXin LI if (which_prog == SWAPON) { 300268a55bcSHiroki Sato arc4random_buf(bpass, sizeof(bpass)); 301268a55bcSHiroki Sato for (i = 0; i < (int)sizeof(bpass); i++) 302268a55bcSHiroki Sato sprintf(&pass[2 * i], "%02x", bpass[i]); 303268a55bcSHiroki Sato pass[sizeof(pass) - 1] = '\0'; 304268a55bcSHiroki Sato 3058f8de1e1SXin LI error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE, 306cb754f61SHiroki Sato dname, pass); 307268a55bcSHiroki Sato if (error) { 308268a55bcSHiroki Sato /* bde device found. Ignore it. */ 3098f8de1e1SXin LI free(dname); 31079ba2f31SHiroki Sato if (qflag == 0) 311268a55bcSHiroki Sato warnx("%s: Device already in use", name); 312268a55bcSHiroki Sato return (NULL); 313268a55bcSHiroki Sato } 3148f8de1e1SXin LI error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE, 315cb754f61SHiroki Sato dname, pass); 3168f8de1e1SXin LI free(dname); 317268a55bcSHiroki Sato if (error) { 318268a55bcSHiroki Sato warnx("gbde (attach) error: %s", name); 319268a55bcSHiroki Sato return (NULL); 320268a55bcSHiroki Sato } 321268a55bcSHiroki Sato } 3228f8de1e1SXin LI 323268a55bcSHiroki Sato ret = swap_on_off_sfile(name, doingall); 324268a55bcSHiroki Sato 3258f8de1e1SXin LI if (which_prog == SWAPOFF) { 3268f8de1e1SXin LI error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname); 3278f8de1e1SXin LI free(dname); 328268a55bcSHiroki Sato if (error) { 329268a55bcSHiroki Sato /* bde device not found. Ignore it. */ 33079ba2f31SHiroki Sato if (qflag == 0) 3318f8de1e1SXin LI warnx("%s: Device not found", name); 332268a55bcSHiroki Sato return (NULL); 333268a55bcSHiroki Sato } 334268a55bcSHiroki Sato } 335268a55bcSHiroki Sato 336268a55bcSHiroki Sato return (ret); 337268a55bcSHiroki Sato } 338268a55bcSHiroki Sato 3390d8a14f9SXin LI /* Build geli(8) arguments from mntops */ 3408f8de1e1SXin LI static char * 3418f8de1e1SXin LI swap_on_geli_args(const char *mntops) 342268a55bcSHiroki Sato { 3438f8de1e1SXin LI const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; 344445bda3fSPawel Jakub Dawidek const char *aflag, *eflag, *lflag, *Tflag, *sflag; 34579ba2f31SHiroki Sato char *p, *args, *token, *string, *ops; 34624cd0f85SEnji Cooper int pagesize; 3478f8de1e1SXin LI size_t pagesize_len; 348268a55bcSHiroki Sato u_long ul; 349268a55bcSHiroki Sato 35079ba2f31SHiroki Sato /* Use built-in defaults for geli(8). */ 3518f8de1e1SXin LI aalgo = ealgo = keylen_str = ""; 352445bda3fSPawel Jakub Dawidek aflag = eflag = lflag = Tflag = ""; 353268a55bcSHiroki Sato 35479ba2f31SHiroki Sato /* We will always specify sectorsize. */ 3558f8de1e1SXin LI sflag = " -s "; 3568f8de1e1SXin LI sectorsize_str = NULL; 357268a55bcSHiroki Sato 3588f8de1e1SXin LI if (mntops != NULL) { 3598f8de1e1SXin LI string = ops = strdup(mntops); 360268a55bcSHiroki Sato 3618f8de1e1SXin LI while ((token = strsep(&string, ",")) != NULL) { 3628f8de1e1SXin LI if ((p = strstr(token, "aalgo=")) == token) { 363268a55bcSHiroki Sato aalgo = p + sizeof("aalgo=") - 1; 3648f8de1e1SXin LI aflag = " -a "; 3658f8de1e1SXin LI } else if ((p = strstr(token, "ealgo=")) == token) { 366268a55bcSHiroki Sato ealgo = p + sizeof("ealgo=") - 1; 3678f8de1e1SXin LI eflag = " -e "; 3688f8de1e1SXin LI } else if ((p = strstr(token, "keylen=")) == token) { 369268a55bcSHiroki Sato keylen_str = p + sizeof("keylen=") - 1; 370268a55bcSHiroki Sato errno = 0; 371268a55bcSHiroki Sato ul = strtoul(keylen_str, &p, 10); 372268a55bcSHiroki Sato if (errno == 0) { 373268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 374268a55bcSHiroki Sato errno = EINVAL; 375268a55bcSHiroki Sato } 376268a55bcSHiroki Sato if (errno) { 377268a55bcSHiroki Sato warn("Invalid keylen: %s", keylen_str); 3788f8de1e1SXin LI free(ops); 379268a55bcSHiroki Sato return (NULL); 380268a55bcSHiroki Sato } 3818f8de1e1SXin LI lflag = " -l "; 3828f8de1e1SXin LI } else if ((p = strstr(token, "sectorsize=")) == token) { 383268a55bcSHiroki Sato sectorsize_str = p + sizeof("sectorsize=") - 1; 384268a55bcSHiroki Sato errno = 0; 385268a55bcSHiroki Sato ul = strtoul(sectorsize_str, &p, 10); 386268a55bcSHiroki Sato if (errno == 0) { 387268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 388268a55bcSHiroki Sato errno = EINVAL; 389268a55bcSHiroki Sato } 390268a55bcSHiroki Sato if (errno) { 39179ba2f31SHiroki Sato warn("Invalid sectorsize: %s", 39279ba2f31SHiroki Sato sectorsize_str); 3938f8de1e1SXin LI free(ops); 394268a55bcSHiroki Sato return (NULL); 395268a55bcSHiroki Sato } 3968d27c200SDmitry Marakasov } else if (strcmp(token, "notrim") == 0) { 397a616b253SDoug Moore if (Eflag) { 398a616b253SDoug Moore warn("Options \"notrim\" and " 399a616b253SDoug Moore "\"trimonce\" conflict"); 400a616b253SDoug Moore free(ops); 401a616b253SDoug Moore return (NULL); 402a616b253SDoug Moore } 403445bda3fSPawel Jakub Dawidek Tflag = " -T "; 4048d27c200SDmitry Marakasov } else if (strcmp(token, "late") == 0) { 4058d27c200SDmitry Marakasov /* ignore known option */ 4068d27c200SDmitry Marakasov } else if (strcmp(token, "noauto") == 0) { 4078d27c200SDmitry Marakasov /* ignore known option */ 408a616b253SDoug Moore } else if (strcmp(token, "sw") == 0) { 409a616b253SDoug Moore /* ignore known option */ 410a616b253SDoug Moore } else if (strcmp(token, "trimonce") == 0) { 411a616b253SDoug Moore /* ignore known option */ 412a616b253SDoug Moore } else { 4138f8de1e1SXin LI warnx("Invalid option: %s", token); 4148f8de1e1SXin LI free(ops); 4158f8de1e1SXin LI return (NULL); 416268a55bcSHiroki Sato } 4178f8de1e1SXin LI } 4188f8de1e1SXin LI } else 4198f8de1e1SXin LI ops = NULL; 420268a55bcSHiroki Sato 4218f8de1e1SXin LI /* 4228f8de1e1SXin LI * If we do not have a sector size at this point, fill in 4238f8de1e1SXin LI * pagesize as sector size. 4248f8de1e1SXin LI */ 4258f8de1e1SXin LI if (sectorsize_str == NULL) { 42679ba2f31SHiroki Sato /* Use pagesize as default sectorsize. */ 4278f8de1e1SXin LI pagesize = getpagesize(); 4288f8de1e1SXin LI pagesize_len = snprintf(NULL, 0, "%d", pagesize) + 1; 4298f8de1e1SXin LI p = alloca(pagesize_len); 4308f8de1e1SXin LI snprintf(p, pagesize_len, "%d", pagesize); 4318f8de1e1SXin LI sectorsize_str = p; 4328f8de1e1SXin LI } 4338f8de1e1SXin LI 43424cd0f85SEnji Cooper (void)asprintf(&args, "%s%s%s%s%s%s%s%s%s -d", 435445bda3fSPawel Jakub Dawidek aflag, aalgo, eflag, ealgo, lflag, keylen_str, Tflag, 4368f8de1e1SXin LI sflag, sectorsize_str); 4378f8de1e1SXin LI 4388f8de1e1SXin LI free(ops); 4398f8de1e1SXin LI return (args); 4408f8de1e1SXin LI } 4418f8de1e1SXin LI 4428f8de1e1SXin LI static const char * 4438f8de1e1SXin LI swap_on_off_geli(const char *name, char *mntops, int doingall) 4448f8de1e1SXin LI { 4458f8de1e1SXin LI struct stat sb; 44679ba2f31SHiroki Sato char *dname, *args; 4478f8de1e1SXin LI int error; 4488f8de1e1SXin LI 4498f8de1e1SXin LI error = stat(name, &sb); 4508f8de1e1SXin LI 4518f8de1e1SXin LI if (which_prog == SWAPON) do { 45279ba2f31SHiroki Sato /* Skip if the .eli device already exists. */ 4538f8de1e1SXin LI if (error == 0) 4548f8de1e1SXin LI break; 4558f8de1e1SXin LI 4568f8de1e1SXin LI args = swap_on_geli_args(mntops); 4578f8de1e1SXin LI if (args == NULL) 4588f8de1e1SXin LI return (NULL); 4598f8de1e1SXin LI 4608f8de1e1SXin LI dname = swap_basename(name); 4618f8de1e1SXin LI if (dname == NULL) { 4628f8de1e1SXin LI free(args); 4638f8de1e1SXin LI return (NULL); 4648f8de1e1SXin LI } 4658f8de1e1SXin LI 4668f8de1e1SXin LI error = run_cmd(NULL, "%s onetime%s %s", _PATH_GELI, args, 467cb754f61SHiroki Sato dname); 4688f8de1e1SXin LI 4698f8de1e1SXin LI free(dname); 4708f8de1e1SXin LI free(args); 4718f8de1e1SXin LI 472268a55bcSHiroki Sato if (error) { 473b68ac800SPedro F. Giffuni /* error occurred during creation. */ 47479ba2f31SHiroki Sato if (qflag == 0) 4758f8de1e1SXin LI warnx("%s: Invalid parameters", name); 476268a55bcSHiroki Sato return (NULL); 477268a55bcSHiroki Sato } 4788f8de1e1SXin LI } while (0); 479268a55bcSHiroki Sato 480268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 481268a55bcSHiroki Sato } 482268a55bcSHiroki Sato 483268a55bcSHiroki Sato static const char * 4848f8de1e1SXin LI swap_on_off_md(const char *name, char *mntops, int doingall) 485268a55bcSHiroki Sato { 486268a55bcSHiroki Sato FILE *sfd; 487268a55bcSHiroki Sato int fd, mdunit, error; 488268a55bcSHiroki Sato const char *ret; 48954282733SXin LI static char mdpath[PATH_MAX], linebuf[PATH_MAX]; 490268a55bcSHiroki Sato char *p, *vnodefile; 491268a55bcSHiroki Sato size_t linelen; 492268a55bcSHiroki Sato u_long ul; 493268a55bcSHiroki Sato 494268a55bcSHiroki Sato fd = -1; 495268a55bcSHiroki Sato sfd = NULL; 496268a55bcSHiroki Sato if (strlen(name) == (sizeof(MD_NAME) - 1)) 497268a55bcSHiroki Sato mdunit = -1; 498268a55bcSHiroki Sato else { 499268a55bcSHiroki Sato errno = 0; 500268a55bcSHiroki Sato ul = strtoul(name + 2, &p, 10); 501268a55bcSHiroki Sato if (errno == 0) { 502268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 503268a55bcSHiroki Sato errno = EINVAL; 504268a55bcSHiroki Sato } 505268a55bcSHiroki Sato if (errno) { 506268a55bcSHiroki Sato warn("Bad device unit: %s", name); 507268a55bcSHiroki Sato return (NULL); 508268a55bcSHiroki Sato } 509268a55bcSHiroki Sato mdunit = (int)ul; 510268a55bcSHiroki Sato } 511268a55bcSHiroki Sato 512268a55bcSHiroki Sato vnodefile = NULL; 513268a55bcSHiroki Sato if ((p = strstr(mntops, "file=")) != NULL) { 514268a55bcSHiroki Sato vnodefile = strdup(p + sizeof("file=") - 1); 515268a55bcSHiroki Sato p = strchr(vnodefile, ','); 516268a55bcSHiroki Sato if (p != NULL) 517268a55bcSHiroki Sato *p = '\0'; 518268a55bcSHiroki Sato } 519268a55bcSHiroki Sato if (vnodefile == NULL) { 520268a55bcSHiroki Sato warnx("file option not found for %s", name); 521268a55bcSHiroki Sato return (NULL); 522268a55bcSHiroki Sato } 523268a55bcSHiroki Sato 5248f8de1e1SXin LI if (which_prog == SWAPON) { 525268a55bcSHiroki Sato if (mdunit == -1) { 526268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 527268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 528268a55bcSHiroki Sato if (error == 0) { 529268a55bcSHiroki Sato /* md device found. Ignore it. */ 530268a55bcSHiroki Sato close(fd); 531268a55bcSHiroki Sato if (!qflag) 532268a55bcSHiroki Sato warnx("%s: Device already in use", 533268a55bcSHiroki Sato vnodefile); 5341bf9e66cSXin LI free(vnodefile); 535268a55bcSHiroki Sato return (NULL); 536268a55bcSHiroki Sato } 537268a55bcSHiroki Sato error = run_cmd(&fd, "%s -a -t vnode -n -f %s", 538268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 539268a55bcSHiroki Sato if (error) { 540268a55bcSHiroki Sato warnx("mdconfig (attach) error: file=%s", 541268a55bcSHiroki Sato vnodefile); 5421bf9e66cSXin LI free(vnodefile); 543268a55bcSHiroki Sato return (NULL); 544268a55bcSHiroki Sato } 545268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 546268a55bcSHiroki Sato if (sfd == NULL) { 547268a55bcSHiroki Sato warn("mdconfig (attach) fdopen error"); 548268a55bcSHiroki Sato ret = NULL; 549268a55bcSHiroki Sato goto err; 550268a55bcSHiroki Sato } 551268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 5521bf6738fSDon Lewis if (p == NULL || 553268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf))) { 554268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output"); 555268a55bcSHiroki Sato ret = NULL; 556268a55bcSHiroki Sato goto err; 557268a55bcSHiroki Sato } 558883b7553SXin LI strlcpy(linebuf, p, linelen); 559268a55bcSHiroki Sato errno = 0; 560268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 561268a55bcSHiroki Sato if (errno == 0) { 562268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 563268a55bcSHiroki Sato errno = EINVAL; 564268a55bcSHiroki Sato } 565268a55bcSHiroki Sato if (errno) { 566268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output: %s", 567268a55bcSHiroki Sato linebuf); 568268a55bcSHiroki Sato ret = NULL; 569268a55bcSHiroki Sato goto err; 570268a55bcSHiroki Sato } 571268a55bcSHiroki Sato mdunit = (int)ul; 572268a55bcSHiroki Sato } else { 573268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 574268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 575268a55bcSHiroki Sato if (error == 0) { 576268a55bcSHiroki Sato /* md device found. Ignore it. */ 577268a55bcSHiroki Sato close(fd); 57879ba2f31SHiroki Sato if (qflag == 0) 579268a55bcSHiroki Sato warnx("md%d on %s: Device already " 580268a55bcSHiroki Sato "in use", mdunit, vnodefile); 5811bf9e66cSXin LI free(vnodefile); 582268a55bcSHiroki Sato return (NULL); 583268a55bcSHiroki Sato } 584268a55bcSHiroki Sato error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", 585268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit, vnodefile); 586268a55bcSHiroki Sato if (error) { 587268a55bcSHiroki Sato warnx("mdconfig (attach) error: " 588268a55bcSHiroki Sato "md%d on file=%s", mdunit, vnodefile); 5891bf9e66cSXin LI free(vnodefile); 590268a55bcSHiroki Sato return (NULL); 591268a55bcSHiroki Sato } 592268a55bcSHiroki Sato } 5938f8de1e1SXin LI } else /* SWAPOFF */ { 594268a55bcSHiroki Sato if (mdunit == -1) { 595268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 596268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 597268a55bcSHiroki Sato if (error) { 598268a55bcSHiroki Sato /* md device not found. Ignore it. */ 599268a55bcSHiroki Sato close(fd); 600268a55bcSHiroki Sato if (!qflag) 601268a55bcSHiroki Sato warnx("md on %s: Device not found", 602268a55bcSHiroki Sato vnodefile); 6031bf9e66cSXin LI free(vnodefile); 604268a55bcSHiroki Sato return (NULL); 605268a55bcSHiroki Sato } 606268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 607268a55bcSHiroki Sato if (sfd == NULL) { 608268a55bcSHiroki Sato warn("mdconfig (list) fdopen error"); 609268a55bcSHiroki Sato ret = NULL; 610268a55bcSHiroki Sato goto err; 611268a55bcSHiroki Sato } 612268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 613883b7553SXin LI if (p == NULL || 614883b7553SXin LI (linelen < 2 || linelen > sizeof(linebuf))) { 615268a55bcSHiroki Sato warn("mdconfig (list) unexpected output"); 616268a55bcSHiroki Sato ret = NULL; 617268a55bcSHiroki Sato goto err; 618268a55bcSHiroki Sato } 619883b7553SXin LI strlcpy(linebuf, p, linelen); 620268a55bcSHiroki Sato p = strchr(linebuf, ' '); 621268a55bcSHiroki Sato if (p != NULL) 622268a55bcSHiroki Sato *p = '\0'; 623268a55bcSHiroki Sato errno = 0; 624268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 625268a55bcSHiroki Sato if (errno == 0) { 626268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 627268a55bcSHiroki Sato errno = EINVAL; 628268a55bcSHiroki Sato } 629268a55bcSHiroki Sato if (errno) { 630268a55bcSHiroki Sato warn("mdconfig (list) unexpected output: %s", 631268a55bcSHiroki Sato linebuf); 632268a55bcSHiroki Sato ret = NULL; 633268a55bcSHiroki Sato goto err; 634268a55bcSHiroki Sato } 635268a55bcSHiroki Sato mdunit = (int)ul; 636268a55bcSHiroki Sato } else { 637268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 638268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 639268a55bcSHiroki Sato if (error) { 640268a55bcSHiroki Sato /* md device not found. Ignore it. */ 641268a55bcSHiroki Sato close(fd); 642268a55bcSHiroki Sato if (!qflag) 643268a55bcSHiroki Sato warnx("md%d on %s: Device not found", 644268a55bcSHiroki Sato mdunit, vnodefile); 6451bf9e66cSXin LI free(vnodefile); 646268a55bcSHiroki Sato return (NULL); 647268a55bcSHiroki Sato } 648268a55bcSHiroki Sato } 649268a55bcSHiroki Sato } 650268a55bcSHiroki Sato snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, 651268a55bcSHiroki Sato MD_NAME, mdunit); 652268a55bcSHiroki Sato mdpath[sizeof(mdpath) - 1] = '\0'; 653268a55bcSHiroki Sato ret = swap_on_off_sfile(mdpath, doingall); 654268a55bcSHiroki Sato 6558f8de1e1SXin LI if (which_prog == SWAPOFF) { 656268a55bcSHiroki Sato if (ret != NULL) { 657268a55bcSHiroki Sato error = run_cmd(NULL, "%s -d -u %d", 658268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit); 659268a55bcSHiroki Sato if (error) 660268a55bcSHiroki Sato warn("mdconfig (detach) detach failed: %s%s%d", 661268a55bcSHiroki Sato _PATH_DEV, MD_NAME, mdunit); 662268a55bcSHiroki Sato } 663268a55bcSHiroki Sato } 664268a55bcSHiroki Sato err: 665268a55bcSHiroki Sato if (sfd != NULL) 666268a55bcSHiroki Sato fclose(sfd); 667268a55bcSHiroki Sato if (fd != -1) 668268a55bcSHiroki Sato close(fd); 6691bf9e66cSXin LI free(vnodefile); 670268a55bcSHiroki Sato return (ret); 671268a55bcSHiroki Sato } 672268a55bcSHiroki Sato 673268a55bcSHiroki Sato static int 674268a55bcSHiroki Sato run_cmd(int *ofd, const char *cmdline, ...) 675268a55bcSHiroki Sato { 676268a55bcSHiroki Sato va_list ap; 677268a55bcSHiroki Sato char **argv, **argvp, *cmd, *p; 678268a55bcSHiroki Sato int argc, pid, status, rv; 679268a55bcSHiroki Sato int pfd[2], nfd, dup2dn; 680268a55bcSHiroki Sato 681268a55bcSHiroki Sato va_start(ap, cmdline); 682268a55bcSHiroki Sato rv = vasprintf(&cmd, cmdline, ap); 683268a55bcSHiroki Sato if (rv == -1) { 684268a55bcSHiroki Sato warn("%s", __func__); 68533c2e470SEnji Cooper va_end(ap); 686268a55bcSHiroki Sato return (rv); 687268a55bcSHiroki Sato } 688268a55bcSHiroki Sato va_end(ap); 689268a55bcSHiroki Sato 690268a55bcSHiroki Sato for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 691268a55bcSHiroki Sato argc++; 692268a55bcSHiroki Sato argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 693268a55bcSHiroki Sato for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 694268a55bcSHiroki Sato if (**argvp != '\0' && (++argvp > &argv[argc])) { 695268a55bcSHiroki Sato *argvp = NULL; 696268a55bcSHiroki Sato break; 697268a55bcSHiroki Sato } 698268a55bcSHiroki Sato /* The argv array ends up NULL-terminated here. */ 699268a55bcSHiroki Sato #if 0 700268a55bcSHiroki Sato { 701268a55bcSHiroki Sato int i; 702268a55bcSHiroki Sato 703268a55bcSHiroki Sato fprintf(stderr, "DEBUG: running:"); 704268a55bcSHiroki Sato /* Should be equivalent to 'cmd' (before strsep, of course). */ 705268a55bcSHiroki Sato for (i = 0; argv[i] != NULL; i++) 706268a55bcSHiroki Sato fprintf(stderr, " %s", argv[i]); 707268a55bcSHiroki Sato fprintf(stderr, "\n"); 708268a55bcSHiroki Sato } 709268a55bcSHiroki Sato #endif 710268a55bcSHiroki Sato dup2dn = 1; 711268a55bcSHiroki Sato if (ofd != NULL) { 712268a55bcSHiroki Sato if (pipe(&pfd[0]) == -1) { 713268a55bcSHiroki Sato warn("%s: pipe", __func__); 714268a55bcSHiroki Sato return (-1); 715268a55bcSHiroki Sato } 716268a55bcSHiroki Sato *ofd = pfd[0]; 717268a55bcSHiroki Sato dup2dn = 0; 718268a55bcSHiroki Sato } 719268a55bcSHiroki Sato pid = fork(); 720268a55bcSHiroki Sato switch (pid) { 721268a55bcSHiroki Sato case 0: 722268a55bcSHiroki Sato /* Child process. */ 723268a55bcSHiroki Sato if (ofd != NULL) 724268a55bcSHiroki Sato if (dup2(pfd[1], STDOUT_FILENO) < 0) 725268a55bcSHiroki Sato err(1, "dup2 in %s", __func__); 726268a55bcSHiroki Sato nfd = open(_PATH_DEVNULL, O_RDWR); 727268a55bcSHiroki Sato if (nfd == -1) 728268a55bcSHiroki Sato err(1, "%s: open %s", __func__, _PATH_DEVNULL); 729268a55bcSHiroki Sato if (dup2(nfd, STDIN_FILENO) < 0) 730268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 731268a55bcSHiroki Sato if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0) 732268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 733268a55bcSHiroki Sato if (dup2(nfd, STDERR_FILENO) < 0) 734268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 735268a55bcSHiroki Sato execv(argv[0], argv); 736268a55bcSHiroki Sato warn("exec: %s", argv[0]); 737268a55bcSHiroki Sato _exit(-1); 738268a55bcSHiroki Sato case -1: 739268a55bcSHiroki Sato err(1, "%s: fork", __func__); 740268a55bcSHiroki Sato } 741268a55bcSHiroki Sato free(cmd); 742268a55bcSHiroki Sato free(argv); 743268a55bcSHiroki Sato while (waitpid(pid, &status, 0) != pid) 744268a55bcSHiroki Sato ; 745268a55bcSHiroki Sato return (WEXITSTATUS(status)); 746268a55bcSHiroki Sato } 747268a55bcSHiroki Sato 7486d5685c7SDoug Moore static int 7496d5685c7SDoug Moore swapon_trim(const char *name) 750a616b253SDoug Moore { 751a616b253SDoug Moore struct stat sb; 752a616b253SDoug Moore off_t ioarg[2], sz; 7536d5685c7SDoug Moore int error, fd; 754a616b253SDoug Moore 755473fe2c0SDoug Moore /* Open a descriptor to create a consumer of the device. */ 756a616b253SDoug Moore fd = open(name, O_WRONLY); 757a616b253SDoug Moore if (fd < 0) 758a616b253SDoug Moore errx(1, "Cannot open %s", name); 759473fe2c0SDoug Moore /* Find the device size. */ 760a616b253SDoug Moore if (fstat(fd, &sb) < 0) 761a616b253SDoug Moore errx(1, "Cannot stat %s", name); 762a616b253SDoug Moore if (S_ISREG(sb.st_mode)) 763a616b253SDoug Moore sz = sb.st_size; 7649035b225SDoug Moore else if (S_ISCHR(sb.st_mode)) { 765a616b253SDoug Moore if (ioctl(fd, DIOCGMEDIASIZE, &sz) != 0) 766a616b253SDoug Moore err(1, "ioctl(DIOCGMEDIASIZE)"); 767a616b253SDoug Moore } else 768a616b253SDoug Moore errx(1, "%s has an invalid file type", name); 769473fe2c0SDoug Moore /* Trim the device. */ 770504f5e29SDoug Moore ioarg[0] = BBSIZE; 771504f5e29SDoug Moore ioarg[1] = sz - BBSIZE; 772a616b253SDoug Moore if (ioctl(fd, DIOCGDELETE, ioarg) != 0) 773a616b253SDoug Moore warn("ioctl(DIOCGDELETE)"); 7746d5685c7SDoug Moore 775473fe2c0SDoug Moore /* Start using the device for swapping, creating a second consumer. */ 7766d5685c7SDoug Moore error = swapon(name); 777473fe2c0SDoug Moore 778473fe2c0SDoug Moore /* 779473fe2c0SDoug Moore * Do not close the device until the swap pager has attempted to create 780473fe2c0SDoug Moore * another consumer. For GELI devices created with the 'detach -l' 781473fe2c0SDoug Moore * option, removing the last consumer causes the device to be detached 782473fe2c0SDoug Moore * - that is, to disappear. This ordering ensures that the device will 783473fe2c0SDoug Moore * not be detached until swapoff is called. 784473fe2c0SDoug Moore */ 785a616b253SDoug Moore close(fd); 7866d5685c7SDoug Moore return (error); 787a616b253SDoug Moore } 788a616b253SDoug Moore 789268a55bcSHiroki Sato static const char * 7908f8de1e1SXin LI swap_on_off_sfile(const char *name, int doingall) 791268a55bcSHiroki Sato { 792268a55bcSHiroki Sato int error; 793268a55bcSHiroki Sato 7946d5685c7SDoug Moore if (which_prog == SWAPON) 7956d5685c7SDoug Moore error = Eflag ? swapon_trim(name) : swapon(name); 796b49b6e0fSKonstantin Belousov else /* SWAPOFF */ 797b49b6e0fSKonstantin Belousov error = swapoff(name, fflag ? SWAPOFF_FORCE : 0); 7988f8de1e1SXin LI 799268a55bcSHiroki Sato if (error == -1) { 8008fae3551SRodney W. Grimes switch (errno) { 8018fae3551SRodney W. Grimes case EBUSY: 80279ba2f31SHiroki Sato if (doingall == 0) 803268a55bcSHiroki Sato warnx("%s: Device already in use", name); 8048fae3551SRodney W. Grimes break; 8054937798dSDavid Schultz case EINVAL: 8064937798dSDavid Schultz if (which_prog == SWAPON) 8074937798dSDavid Schultz warnx("%s: NSWAPDEV limit reached", name); 80879ba2f31SHiroki Sato else if (doingall == 0) 8094937798dSDavid Schultz warn("%s", name); 8104937798dSDavid Schultz break; 8118fae3551SRodney W. Grimes default: 8126da7f378SPhilippe Charnier warn("%s", name); 8138fae3551SRodney W. Grimes break; 8148fae3551SRodney W. Grimes } 815268a55bcSHiroki Sato return (NULL); 8168fae3551SRodney W. Grimes } 817268a55bcSHiroki Sato return (name); 8188fae3551SRodney W. Grimes } 8198fae3551SRodney W. Grimes 8206da7f378SPhilippe Charnier static void 821a420c811SMatthew Dillon usage(void) 8228fae3551SRodney W. Grimes { 82379ba2f31SHiroki Sato 824a420c811SMatthew Dillon fprintf(stderr, "usage: %s ", getprogname()); 825a420c811SMatthew Dillon switch(orig_prog) { 826a420c811SMatthew Dillon case SWAPON: 827a616b253SDoug Moore fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n"); 828a616b253SDoug Moore break; 8298d646af5SRuslan Ermilov case SWAPOFF: 8301aa249c9SKonstantin Belousov fprintf(stderr, "[-F fstab] -afLq | file ...\n"); 831a420c811SMatthew Dillon break; 832a420c811SMatthew Dillon case SWAPCTL: 8332e64768cSPawel Jakub Dawidek fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 834a420c811SMatthew Dillon break; 835a420c811SMatthew Dillon } 8368fae3551SRodney W. Grimes exit(1); 8378fae3551SRodney W. Grimes } 83892da00bbSMatthew Dillon 839a420c811SMatthew Dillon static void 8402e64768cSPawel Jakub Dawidek sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 8412e64768cSPawel Jakub Dawidek long blocksize) 8422e64768cSPawel Jakub Dawidek { 8432e64768cSPawel Jakub Dawidek char tmp[16]; 8442e64768cSPawel Jakub Dawidek 84579ba2f31SHiroki Sato if (hflag == 'H') { 8462e64768cSPawel Jakub Dawidek humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 8472e64768cSPawel Jakub Dawidek HN_B | HN_NOSPACE | HN_DECIMAL); 8482e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*s", hlen, tmp); 84979ba2f31SHiroki Sato } else 8502e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 8512e64768cSPawel Jakub Dawidek } 8522e64768cSPawel Jakub Dawidek 8532e64768cSPawel Jakub Dawidek static void 854a420c811SMatthew Dillon swaplist(int lflag, int sflag, int hflag) 85592da00bbSMatthew Dillon { 856a420c811SMatthew Dillon size_t mibsize, size; 857a420c811SMatthew Dillon struct xswdev xsw; 85869095b02SMike Barcroft int hlen, mib[16], n, pagesize; 859a420c811SMatthew Dillon long blocksize; 860a420c811SMatthew Dillon long long total = 0; 861a420c811SMatthew Dillon long long used = 0; 862a420c811SMatthew Dillon long long tmp_total; 863a420c811SMatthew Dillon long long tmp_used; 8642e64768cSPawel Jakub Dawidek char buf[32]; 86592da00bbSMatthew Dillon 866a420c811SMatthew Dillon pagesize = getpagesize(); 867a420c811SMatthew Dillon switch(hflag) { 8682e64768cSPawel Jakub Dawidek case 'G': 8692e64768cSPawel Jakub Dawidek blocksize = 1024 * 1024 * 1024; 8702e64768cSPawel Jakub Dawidek strlcpy(buf, "1GB-blocks", sizeof(buf)); 8712e64768cSPawel Jakub Dawidek hlen = 10; 8722e64768cSPawel Jakub Dawidek break; 8732e64768cSPawel Jakub Dawidek case 'H': 8742e64768cSPawel Jakub Dawidek blocksize = -1; 8752e64768cSPawel Jakub Dawidek strlcpy(buf, "Bytes", sizeof(buf)); 8762e64768cSPawel Jakub Dawidek hlen = 10; 8772e64768cSPawel Jakub Dawidek break; 878a420c811SMatthew Dillon case 'K': 879a420c811SMatthew Dillon blocksize = 1024; 8802e64768cSPawel Jakub Dawidek strlcpy(buf, "1kB-blocks", sizeof(buf)); 881a420c811SMatthew Dillon hlen = 10; 882a420c811SMatthew Dillon break; 883a420c811SMatthew Dillon case 'M': 884a420c811SMatthew Dillon blocksize = 1024 * 1024; 8852e64768cSPawel Jakub Dawidek strlcpy(buf, "1MB-blocks", sizeof(buf)); 886a420c811SMatthew Dillon hlen = 10; 887a420c811SMatthew Dillon break; 888a420c811SMatthew Dillon default: 8899255f327SMike Barcroft getbsize(&hlen, &blocksize); 8902e64768cSPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 891a420c811SMatthew Dillon break; 89292da00bbSMatthew Dillon } 893a420c811SMatthew Dillon 89479ba2f31SHiroki Sato mibsize = nitems(mib); 895a420c811SMatthew Dillon if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 896a420c811SMatthew Dillon err(1, "sysctlnametomib()"); 897a420c811SMatthew Dillon 898a420c811SMatthew Dillon if (lflag) { 899a420c811SMatthew Dillon printf("%-13s %*s %*s\n", 900a420c811SMatthew Dillon "Device:", 901a420c811SMatthew Dillon hlen, buf, 902a420c811SMatthew Dillon hlen, "Used:"); 903a420c811SMatthew Dillon } 904a420c811SMatthew Dillon 905a420c811SMatthew Dillon for (n = 0; ; ++n) { 906a420c811SMatthew Dillon mib[mibsize] = n; 907a420c811SMatthew Dillon size = sizeof xsw; 90816fc3635SMark Murray if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 909a420c811SMatthew Dillon break; 910a420c811SMatthew Dillon if (xsw.xsw_version != XSWDEV_VERSION) 911a420c811SMatthew Dillon errx(1, "xswdev version mismatch"); 912a420c811SMatthew Dillon 9132e64768cSPawel Jakub Dawidek tmp_total = (long long)xsw.xsw_nblks * pagesize; 9142e64768cSPawel Jakub Dawidek tmp_used = (long long)xsw.xsw_used * pagesize; 915a420c811SMatthew Dillon total += tmp_total; 916a420c811SMatthew Dillon used += tmp_used; 917a420c811SMatthew Dillon if (lflag) { 9182e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 9192e64768cSPawel Jakub Dawidek blocksize); 9202e64768cSPawel Jakub Dawidek printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 9212e64768cSPawel Jakub Dawidek buf); 9222e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 9232e64768cSPawel Jakub Dawidek blocksize); 9242e64768cSPawel Jakub Dawidek printf("%s\n", buf); 925a420c811SMatthew Dillon } 926a420c811SMatthew Dillon } 927a420c811SMatthew Dillon if (errno != ENOENT) 928a420c811SMatthew Dillon err(1, "sysctl()"); 929a420c811SMatthew Dillon 930a420c811SMatthew Dillon if (sflag) { 9312e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 9322e64768cSPawel Jakub Dawidek printf("Total: %s ", buf); 9332e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 9342e64768cSPawel Jakub Dawidek printf("%s\n", buf); 935a420c811SMatthew Dillon } 936a420c811SMatthew Dillon } 937a420c811SMatthew Dillon 938