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> 48268a55bcSHiroki Sato #include <sys/mdioctl.h> 49268a55bcSHiroki Sato #include <sys/stat.h> 50a420c811SMatthew Dillon #include <sys/sysctl.h> 51268a55bcSHiroki Sato #include <sys/wait.h> 526004362eSDavid Schultz #include <vm/vm_param.h> 53a420c811SMatthew Dillon 546da7f378SPhilippe Charnier #include <err.h> 55e798a806SPhilippe Charnier #include <errno.h> 56268a55bcSHiroki Sato #include <fcntl.h> 57268a55bcSHiroki Sato #include <fnmatch.h> 58e798a806SPhilippe Charnier #include <fstab.h> 59268a55bcSHiroki Sato #include <libgen.h> 60268a55bcSHiroki Sato #include <libutil.h> 61268a55bcSHiroki Sato #include <limits.h> 62268a55bcSHiroki Sato #include <paths.h> 63268a55bcSHiroki Sato #include <stdarg.h> 64e798a806SPhilippe Charnier #include <stdio.h> 65cafefe8cSDima Dorfman #include <stdlib.h> 66e798a806SPhilippe Charnier #include <string.h> 67e798a806SPhilippe Charnier #include <unistd.h> 688fae3551SRodney W. Grimes 69a420c811SMatthew Dillon static void usage(void); 708f8de1e1SXin LI static const char *swap_on_off(const char *, int, char *); 718f8de1e1SXin LI static const char *swap_on_off_gbde(const char *, int); 728f8de1e1SXin LI static const char *swap_on_off_geli(const char *, char *, int); 738f8de1e1SXin LI static const char *swap_on_off_md(const char *, char *, int); 748f8de1e1SXin LI static const char *swap_on_off_sfile(const char *, int); 75a420c811SMatthew Dillon static void swaplist(int, int, int); 76268a55bcSHiroki Sato static int run_cmd(int *, const char *, ...) __printflike(2, 3); 77a420c811SMatthew Dillon 781efe3c6bSEd Schouten static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 7938994f93SPoul-Henning Kamp 80a616b253SDoug Moore static int Eflag, qflag; 81268a55bcSHiroki Sato 8238994f93SPoul-Henning Kamp int 8338994f93SPoul-Henning Kamp main(int argc, char **argv) 848fae3551SRodney W. Grimes { 853d438ad6SDavid E. O'Brien struct fstab *fsp; 86268a55bcSHiroki Sato const char *swfile; 87a420c811SMatthew Dillon char *ptr; 8879ba2f31SHiroki Sato int ret, ch, doall; 8979ba2f31SHiroki Sato int sflag, lflag, late, hflag; 90633d2bc5SMaxim Sobolev const char *etc_fstab; 9192da00bbSMatthew Dillon 9279ba2f31SHiroki Sato sflag = lflag = late = hflag = 0; 93a420c811SMatthew Dillon if ((ptr = strrchr(argv[0], '/')) == NULL) 94a420c811SMatthew Dillon ptr = argv[0]; 9579ba2f31SHiroki Sato if (strstr(ptr, "swapon") != NULL) 96a420c811SMatthew Dillon which_prog = SWAPON; 9779ba2f31SHiroki Sato else if (strstr(ptr, "swapoff") != NULL) 98a420c811SMatthew Dillon which_prog = SWAPOFF; 99a420c811SMatthew Dillon orig_prog = which_prog; 1008fae3551SRodney W. Grimes 1018fae3551SRodney W. Grimes doall = 0; 102633d2bc5SMaxim Sobolev etc_fstab = NULL; 103a616b253SDoug Moore while ((ch = getopt(argc, argv, "AadEghklLmqsUF:")) != -1) { 104a420c811SMatthew Dillon switch(ch) { 105a420c811SMatthew Dillon case 'A': 106a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 1078fae3551SRodney W. Grimes doall = 1; 108a420c811SMatthew Dillon which_prog = SWAPON; 10979ba2f31SHiroki Sato } else 110a420c811SMatthew Dillon usage(); 111a420c811SMatthew Dillon break; 112a420c811SMatthew Dillon case 'a': 113a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) 114a420c811SMatthew Dillon doall = 1; 115a420c811SMatthew Dillon else 116a420c811SMatthew Dillon which_prog = SWAPON; 117a420c811SMatthew Dillon break; 118a420c811SMatthew Dillon case 'd': 119a420c811SMatthew Dillon if (which_prog == SWAPCTL) 120a420c811SMatthew Dillon which_prog = SWAPOFF; 121a420c811SMatthew Dillon else 122a420c811SMatthew Dillon usage(); 123a420c811SMatthew Dillon break; 124a616b253SDoug Moore case 'E': 125a616b253SDoug Moore if (which_prog == SWAPON) 126a616b253SDoug Moore Eflag = 2; 127a616b253SDoug Moore else 128a616b253SDoug Moore usage(); 129a616b253SDoug Moore break; 1302e64768cSPawel Jakub Dawidek case 'g': 1312e64768cSPawel Jakub Dawidek hflag = 'G'; 1322e64768cSPawel Jakub Dawidek break; 1332e64768cSPawel Jakub Dawidek case 'h': 1342e64768cSPawel Jakub Dawidek hflag = 'H'; 1352e64768cSPawel Jakub Dawidek break; 1362e64768cSPawel Jakub Dawidek case 'k': 1372e64768cSPawel Jakub Dawidek hflag = 'K'; 138a420c811SMatthew Dillon break; 139a420c811SMatthew Dillon case 'l': 140a420c811SMatthew Dillon lflag = 1; 141a420c811SMatthew Dillon break; 142268a55bcSHiroki Sato case 'L': 143268a55bcSHiroki Sato late = 1; 144268a55bcSHiroki Sato break; 1452e64768cSPawel Jakub Dawidek case 'm': 146a420c811SMatthew Dillon hflag = 'M'; 147a420c811SMatthew Dillon break; 14845a5dc93SMike Makonnen case 'q': 14945a5dc93SMike Makonnen if (which_prog == SWAPON || which_prog == SWAPOFF) 15045a5dc93SMike Makonnen qflag = 1; 15145a5dc93SMike Makonnen break; 1522e64768cSPawel Jakub Dawidek case 's': 1532e64768cSPawel Jakub Dawidek sflag = 1; 154a420c811SMatthew Dillon break; 155a420c811SMatthew Dillon case 'U': 156a420c811SMatthew Dillon if (which_prog == SWAPCTL) { 157a420c811SMatthew Dillon doall = 1; 158a420c811SMatthew Dillon which_prog = SWAPOFF; 15979ba2f31SHiroki Sato } else 160a420c811SMatthew Dillon usage(); 1618fae3551SRodney W. Grimes break; 162633d2bc5SMaxim Sobolev case 'F': 163633d2bc5SMaxim Sobolev etc_fstab = optarg; 164633d2bc5SMaxim Sobolev break; 1658fae3551SRodney W. Grimes case '?': 1668fae3551SRodney W. Grimes default: 167a420c811SMatthew Dillon usage(); 168a420c811SMatthew Dillon } 1698fae3551SRodney W. Grimes } 1708fae3551SRodney W. Grimes argv += optind; 1718fae3551SRodney W. Grimes 172ce458f42SEd Schouten ret = 0; 173268a55bcSHiroki Sato swfile = NULL; 174633d2bc5SMaxim Sobolev if (etc_fstab != NULL) 175633d2bc5SMaxim Sobolev setfstab(etc_fstab); 176a420c811SMatthew Dillon if (which_prog == SWAPON || which_prog == SWAPOFF) { 177a420c811SMatthew Dillon if (doall) { 17838994f93SPoul-Henning Kamp while ((fsp = getfsent()) != NULL) { 1794139627dSHiroki Sato if (strcmp(fsp->fs_type, FSTAB_SW) != 0) 1808fae3551SRodney W. Grimes continue; 1814139627dSHiroki Sato if (strstr(fsp->fs_mntops, "noauto") != NULL) 1827fc4a454SJordan K. Hubbard continue; 183268a55bcSHiroki Sato if (which_prog != SWAPOFF && 1841482f982SHiroki Sato strstr(fsp->fs_mntops, "late") && 1854139627dSHiroki Sato late == 0) 186268a55bcSHiroki Sato continue; 1877627b330SJilles Tjoelker if (which_prog == SWAPOFF && 1887627b330SJilles Tjoelker strstr(fsp->fs_mntops, "late") == NULL && 1897627b330SJilles Tjoelker late != 0) 1907627b330SJilles Tjoelker continue; 191a616b253SDoug Moore Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL); 192268a55bcSHiroki Sato swfile = swap_on_off(fsp->fs_spec, 1, 193268a55bcSHiroki Sato fsp->fs_mntops); 194a616b253SDoug Moore Eflag &= ~1; 195268a55bcSHiroki Sato if (swfile == NULL) { 196ce458f42SEd Schouten ret = 1; 197268a55bcSHiroki Sato continue; 198268a55bcSHiroki Sato } 19979ba2f31SHiroki Sato if (qflag == 0) { 20092da00bbSMatthew Dillon printf("%s: %sing %s as swap device\n", 20145a5dc93SMike Makonnen getprogname(), 202268a55bcSHiroki Sato (which_prog == SWAPOFF) ? 203268a55bcSHiroki Sato "remov" : "add", swfile); 204a420c811SMatthew Dillon } 205a420c811SMatthew Dillon } 20679ba2f31SHiroki Sato } else if (*argv == NULL) 207a420c811SMatthew Dillon usage(); 208a420c811SMatthew Dillon for (; *argv; ++argv) { 209268a55bcSHiroki Sato swfile = swap_on_off(*argv, 0, NULL); 210268a55bcSHiroki Sato if (swfile == NULL) { 211ce458f42SEd Schouten ret = 1; 212268a55bcSHiroki Sato continue; 213268a55bcSHiroki Sato } 214268a55bcSHiroki Sato if (orig_prog == SWAPCTL) { 215a420c811SMatthew Dillon printf("%s: %sing %s as swap device\n", 216268a55bcSHiroki Sato getprogname(), 217268a55bcSHiroki Sato (which_prog == SWAPOFF) ? "remov" : "add", 218268a55bcSHiroki Sato swfile); 219a420c811SMatthew Dillon } 220a420c811SMatthew Dillon } 221a420c811SMatthew Dillon } else { 222a420c811SMatthew Dillon if (lflag || sflag) 223a420c811SMatthew Dillon swaplist(lflag, sflag, hflag); 224a420c811SMatthew Dillon else 225a420c811SMatthew Dillon usage(); 226a420c811SMatthew Dillon } 227ce458f42SEd Schouten exit(ret); 2288fae3551SRodney W. Grimes } 2298fae3551SRodney W. Grimes 230268a55bcSHiroki Sato static const char * 2318f8de1e1SXin LI swap_on_off(const char *name, int doingall, char *mntops) 2328fae3551SRodney W. Grimes { 233e47c947eSEd Schouten char *base, *basebuf; 234268a55bcSHiroki Sato 235268a55bcSHiroki Sato /* Swap on vnode-backed md(4) device. */ 236268a55bcSHiroki Sato if (mntops != NULL && 2378f8de1e1SXin LI (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || 2388f8de1e1SXin LI fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || 239268a55bcSHiroki Sato strncmp(_PATH_DEV MD_NAME, name, 240268a55bcSHiroki Sato sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || 241268a55bcSHiroki Sato strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) 242268a55bcSHiroki Sato return (swap_on_off_md(name, mntops, doingall)); 243268a55bcSHiroki Sato 244e47c947eSEd Schouten basebuf = strdup(name); 245e47c947eSEd Schouten base = basename(basebuf); 2468f8de1e1SXin LI 2478f8de1e1SXin LI /* Swap on encrypted device by GEOM_BDE. */ 248e47c947eSEd Schouten if (fnmatch("*.bde", base, 0) == 0) { 249e47c947eSEd Schouten free(basebuf); 250268a55bcSHiroki Sato return (swap_on_off_gbde(name, doingall)); 251e47c947eSEd Schouten } 252268a55bcSHiroki Sato 253268a55bcSHiroki Sato /* Swap on encrypted device by GEOM_ELI. */ 254e47c947eSEd Schouten if (fnmatch("*.eli", base, 0) == 0) { 255e47c947eSEd Schouten free(basebuf); 256268a55bcSHiroki Sato return (swap_on_off_geli(name, mntops, doingall)); 257e47c947eSEd Schouten } 258268a55bcSHiroki Sato 259268a55bcSHiroki Sato /* Swap on special file. */ 260e47c947eSEd Schouten free(basebuf); 261268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 262268a55bcSHiroki Sato } 263268a55bcSHiroki Sato 2648f8de1e1SXin LI /* Strip off .bde or .eli suffix from swap device name */ 2658f8de1e1SXin LI static char * 2668f8de1e1SXin LI swap_basename(const char *name) 267268a55bcSHiroki Sato { 268cb754f61SHiroki Sato char *dname, *p; 269268a55bcSHiroki Sato 270cb754f61SHiroki Sato dname = strdup(name); 271cb754f61SHiroki Sato p = strrchr(dname, '.'); 2728f8de1e1SXin LI /* assert(p != NULL); */ 273268a55bcSHiroki Sato *p = '\0'; 274268a55bcSHiroki Sato 2758f8de1e1SXin LI return (dname); 2768f8de1e1SXin LI } 2778f8de1e1SXin LI 2788f8de1e1SXin LI static const char * 2798f8de1e1SXin LI swap_on_off_gbde(const char *name, int doingall) 2808f8de1e1SXin LI { 2818f8de1e1SXin LI const char *ret; 2821fdb18b0SJilles Tjoelker char pass[64 * 2 + 1]; 2831fdb18b0SJilles Tjoelker unsigned char bpass[64]; 2848f8de1e1SXin LI char *dname; 2858f8de1e1SXin LI int i, error; 2868f8de1e1SXin LI 2878f8de1e1SXin LI dname = swap_basename(name); 2888f8de1e1SXin LI if (dname == NULL) 2898f8de1e1SXin LI return (NULL); 2908f8de1e1SXin LI 2918f8de1e1SXin LI if (which_prog == SWAPON) { 292268a55bcSHiroki Sato arc4random_buf(bpass, sizeof(bpass)); 293268a55bcSHiroki Sato for (i = 0; i < (int)sizeof(bpass); i++) 294268a55bcSHiroki Sato sprintf(&pass[2 * i], "%02x", bpass[i]); 295268a55bcSHiroki Sato pass[sizeof(pass) - 1] = '\0'; 296268a55bcSHiroki Sato 2978f8de1e1SXin LI error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE, 298cb754f61SHiroki Sato dname, pass); 299268a55bcSHiroki Sato if (error) { 300268a55bcSHiroki Sato /* bde device found. Ignore it. */ 3018f8de1e1SXin LI free(dname); 30279ba2f31SHiroki Sato if (qflag == 0) 303268a55bcSHiroki Sato warnx("%s: Device already in use", name); 304268a55bcSHiroki Sato return (NULL); 305268a55bcSHiroki Sato } 3068f8de1e1SXin LI error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE, 307cb754f61SHiroki Sato dname, pass); 3088f8de1e1SXin LI free(dname); 309268a55bcSHiroki Sato if (error) { 310268a55bcSHiroki Sato warnx("gbde (attach) error: %s", name); 311268a55bcSHiroki Sato return (NULL); 312268a55bcSHiroki Sato } 313268a55bcSHiroki Sato } 3148f8de1e1SXin LI 315268a55bcSHiroki Sato ret = swap_on_off_sfile(name, doingall); 316268a55bcSHiroki Sato 3178f8de1e1SXin LI if (which_prog == SWAPOFF) { 3188f8de1e1SXin LI error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname); 3198f8de1e1SXin LI free(dname); 320268a55bcSHiroki Sato if (error) { 321268a55bcSHiroki Sato /* bde device not found. Ignore it. */ 32279ba2f31SHiroki Sato if (qflag == 0) 3238f8de1e1SXin LI warnx("%s: Device not found", name); 324268a55bcSHiroki Sato return (NULL); 325268a55bcSHiroki Sato } 326268a55bcSHiroki Sato } 327268a55bcSHiroki Sato 328268a55bcSHiroki Sato return (ret); 329268a55bcSHiroki Sato } 330268a55bcSHiroki Sato 3310d8a14f9SXin LI /* Build geli(8) arguments from mntops */ 3328f8de1e1SXin LI static char * 3338f8de1e1SXin LI swap_on_geli_args(const char *mntops) 334268a55bcSHiroki Sato { 3358f8de1e1SXin LI const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; 336445bda3fSPawel Jakub Dawidek const char *aflag, *eflag, *lflag, *Tflag, *sflag; 33779ba2f31SHiroki Sato char *p, *args, *token, *string, *ops; 33824cd0f85SEnji Cooper int pagesize; 3398f8de1e1SXin LI size_t pagesize_len; 340268a55bcSHiroki Sato u_long ul; 341268a55bcSHiroki Sato 34279ba2f31SHiroki Sato /* Use built-in defaults for geli(8). */ 3438f8de1e1SXin LI aalgo = ealgo = keylen_str = ""; 344445bda3fSPawel Jakub Dawidek aflag = eflag = lflag = Tflag = ""; 345268a55bcSHiroki Sato 34679ba2f31SHiroki Sato /* We will always specify sectorsize. */ 3478f8de1e1SXin LI sflag = " -s "; 3488f8de1e1SXin LI sectorsize_str = NULL; 349268a55bcSHiroki Sato 3508f8de1e1SXin LI if (mntops != NULL) { 3518f8de1e1SXin LI string = ops = strdup(mntops); 352268a55bcSHiroki Sato 3538f8de1e1SXin LI while ((token = strsep(&string, ",")) != NULL) { 3548f8de1e1SXin LI if ((p = strstr(token, "aalgo=")) == token) { 355268a55bcSHiroki Sato aalgo = p + sizeof("aalgo=") - 1; 3568f8de1e1SXin LI aflag = " -a "; 3578f8de1e1SXin LI } else if ((p = strstr(token, "ealgo=")) == token) { 358268a55bcSHiroki Sato ealgo = p + sizeof("ealgo=") - 1; 3598f8de1e1SXin LI eflag = " -e "; 3608f8de1e1SXin LI } else if ((p = strstr(token, "keylen=")) == token) { 361268a55bcSHiroki Sato keylen_str = p + sizeof("keylen=") - 1; 362268a55bcSHiroki Sato errno = 0; 363268a55bcSHiroki Sato ul = strtoul(keylen_str, &p, 10); 364268a55bcSHiroki Sato if (errno == 0) { 365268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 366268a55bcSHiroki Sato errno = EINVAL; 367268a55bcSHiroki Sato } 368268a55bcSHiroki Sato if (errno) { 369268a55bcSHiroki Sato warn("Invalid keylen: %s", keylen_str); 3708f8de1e1SXin LI free(ops); 371268a55bcSHiroki Sato return (NULL); 372268a55bcSHiroki Sato } 3738f8de1e1SXin LI lflag = " -l "; 3748f8de1e1SXin LI } else if ((p = strstr(token, "sectorsize=")) == token) { 375268a55bcSHiroki Sato sectorsize_str = p + sizeof("sectorsize=") - 1; 376268a55bcSHiroki Sato errno = 0; 377268a55bcSHiroki Sato ul = strtoul(sectorsize_str, &p, 10); 378268a55bcSHiroki Sato if (errno == 0) { 379268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 380268a55bcSHiroki Sato errno = EINVAL; 381268a55bcSHiroki Sato } 382268a55bcSHiroki Sato if (errno) { 38379ba2f31SHiroki Sato warn("Invalid sectorsize: %s", 38479ba2f31SHiroki Sato sectorsize_str); 3858f8de1e1SXin LI free(ops); 386268a55bcSHiroki Sato return (NULL); 387268a55bcSHiroki Sato } 3888d27c200SDmitry Marakasov } else if (strcmp(token, "notrim") == 0) { 389a616b253SDoug Moore if (Eflag) { 390a616b253SDoug Moore warn("Options \"notrim\" and " 391a616b253SDoug Moore "\"trimonce\" conflict"); 392a616b253SDoug Moore free(ops); 393a616b253SDoug Moore return (NULL); 394a616b253SDoug Moore } 395445bda3fSPawel Jakub Dawidek Tflag = " -T "; 3968d27c200SDmitry Marakasov } else if (strcmp(token, "late") == 0) { 3978d27c200SDmitry Marakasov /* ignore known option */ 3988d27c200SDmitry Marakasov } else if (strcmp(token, "noauto") == 0) { 3998d27c200SDmitry Marakasov /* ignore known option */ 400a616b253SDoug Moore } else if (strcmp(token, "sw") == 0) { 401a616b253SDoug Moore /* ignore known option */ 402a616b253SDoug Moore } else if (strcmp(token, "trimonce") == 0) { 403a616b253SDoug Moore /* ignore known option */ 404a616b253SDoug Moore } else { 4058f8de1e1SXin LI warnx("Invalid option: %s", token); 4068f8de1e1SXin LI free(ops); 4078f8de1e1SXin LI return (NULL); 408268a55bcSHiroki Sato } 4098f8de1e1SXin LI } 4108f8de1e1SXin LI } else 4118f8de1e1SXin LI ops = NULL; 412268a55bcSHiroki Sato 4138f8de1e1SXin LI /* 4148f8de1e1SXin LI * If we do not have a sector size at this point, fill in 4158f8de1e1SXin LI * pagesize as sector size. 4168f8de1e1SXin LI */ 4178f8de1e1SXin LI if (sectorsize_str == NULL) { 41879ba2f31SHiroki Sato /* Use pagesize as default sectorsize. */ 4198f8de1e1SXin LI pagesize = getpagesize(); 4208f8de1e1SXin LI pagesize_len = snprintf(NULL, 0, "%d", pagesize) + 1; 4218f8de1e1SXin LI p = alloca(pagesize_len); 4228f8de1e1SXin LI snprintf(p, pagesize_len, "%d", pagesize); 4238f8de1e1SXin LI sectorsize_str = p; 4248f8de1e1SXin LI } 4258f8de1e1SXin LI 42624cd0f85SEnji Cooper (void)asprintf(&args, "%s%s%s%s%s%s%s%s%s -d", 427445bda3fSPawel Jakub Dawidek aflag, aalgo, eflag, ealgo, lflag, keylen_str, Tflag, 4288f8de1e1SXin LI sflag, sectorsize_str); 4298f8de1e1SXin LI 4308f8de1e1SXin LI free(ops); 4318f8de1e1SXin LI return (args); 4328f8de1e1SXin LI } 4338f8de1e1SXin LI 4348f8de1e1SXin LI static const char * 4358f8de1e1SXin LI swap_on_off_geli(const char *name, char *mntops, int doingall) 4368f8de1e1SXin LI { 4378f8de1e1SXin LI struct stat sb; 43879ba2f31SHiroki Sato char *dname, *args; 4398f8de1e1SXin LI int error; 4408f8de1e1SXin LI 4418f8de1e1SXin LI error = stat(name, &sb); 4428f8de1e1SXin LI 4438f8de1e1SXin LI if (which_prog == SWAPON) do { 44479ba2f31SHiroki Sato /* Skip if the .eli device already exists. */ 4458f8de1e1SXin LI if (error == 0) 4468f8de1e1SXin LI break; 4478f8de1e1SXin LI 4488f8de1e1SXin LI args = swap_on_geli_args(mntops); 4498f8de1e1SXin LI if (args == NULL) 4508f8de1e1SXin LI return (NULL); 4518f8de1e1SXin LI 4528f8de1e1SXin LI dname = swap_basename(name); 4538f8de1e1SXin LI if (dname == NULL) { 4548f8de1e1SXin LI free(args); 4558f8de1e1SXin LI return (NULL); 4568f8de1e1SXin LI } 4578f8de1e1SXin LI 4588f8de1e1SXin LI error = run_cmd(NULL, "%s onetime%s %s", _PATH_GELI, args, 459cb754f61SHiroki Sato dname); 4608f8de1e1SXin LI 4618f8de1e1SXin LI free(dname); 4628f8de1e1SXin LI free(args); 4638f8de1e1SXin LI 464268a55bcSHiroki Sato if (error) { 465b68ac800SPedro F. Giffuni /* error occurred during creation. */ 46679ba2f31SHiroki Sato if (qflag == 0) 4678f8de1e1SXin LI warnx("%s: Invalid parameters", name); 468268a55bcSHiroki Sato return (NULL); 469268a55bcSHiroki Sato } 4708f8de1e1SXin LI } while (0); 471268a55bcSHiroki Sato 472268a55bcSHiroki Sato return (swap_on_off_sfile(name, doingall)); 473268a55bcSHiroki Sato } 474268a55bcSHiroki Sato 475268a55bcSHiroki Sato static const char * 4768f8de1e1SXin LI swap_on_off_md(const char *name, char *mntops, int doingall) 477268a55bcSHiroki Sato { 478268a55bcSHiroki Sato FILE *sfd; 479268a55bcSHiroki Sato int fd, mdunit, error; 480268a55bcSHiroki Sato const char *ret; 48154282733SXin LI static char mdpath[PATH_MAX], linebuf[PATH_MAX]; 482268a55bcSHiroki Sato char *p, *vnodefile; 483268a55bcSHiroki Sato size_t linelen; 484268a55bcSHiroki Sato u_long ul; 485268a55bcSHiroki Sato 486268a55bcSHiroki Sato fd = -1; 487268a55bcSHiroki Sato sfd = NULL; 488268a55bcSHiroki Sato if (strlen(name) == (sizeof(MD_NAME) - 1)) 489268a55bcSHiroki Sato mdunit = -1; 490268a55bcSHiroki Sato else { 491268a55bcSHiroki Sato errno = 0; 492268a55bcSHiroki Sato ul = strtoul(name + 2, &p, 10); 493268a55bcSHiroki Sato if (errno == 0) { 494268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 495268a55bcSHiroki Sato errno = EINVAL; 496268a55bcSHiroki Sato } 497268a55bcSHiroki Sato if (errno) { 498268a55bcSHiroki Sato warn("Bad device unit: %s", name); 499268a55bcSHiroki Sato return (NULL); 500268a55bcSHiroki Sato } 501268a55bcSHiroki Sato mdunit = (int)ul; 502268a55bcSHiroki Sato } 503268a55bcSHiroki Sato 504268a55bcSHiroki Sato vnodefile = NULL; 505268a55bcSHiroki Sato if ((p = strstr(mntops, "file=")) != NULL) { 506268a55bcSHiroki Sato vnodefile = strdup(p + sizeof("file=") - 1); 507268a55bcSHiroki Sato p = strchr(vnodefile, ','); 508268a55bcSHiroki Sato if (p != NULL) 509268a55bcSHiroki Sato *p = '\0'; 510268a55bcSHiroki Sato } 511268a55bcSHiroki Sato if (vnodefile == NULL) { 512268a55bcSHiroki Sato warnx("file option not found for %s", name); 513268a55bcSHiroki Sato return (NULL); 514268a55bcSHiroki Sato } 515268a55bcSHiroki Sato 5168f8de1e1SXin LI if (which_prog == SWAPON) { 517268a55bcSHiroki Sato if (mdunit == -1) { 518268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 519268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 520268a55bcSHiroki Sato if (error == 0) { 521268a55bcSHiroki Sato /* md device found. Ignore it. */ 522268a55bcSHiroki Sato close(fd); 523268a55bcSHiroki Sato if (!qflag) 524268a55bcSHiroki Sato warnx("%s: Device already in use", 525268a55bcSHiroki Sato vnodefile); 5261bf9e66cSXin LI free(vnodefile); 527268a55bcSHiroki Sato return (NULL); 528268a55bcSHiroki Sato } 529268a55bcSHiroki Sato error = run_cmd(&fd, "%s -a -t vnode -n -f %s", 530268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 531268a55bcSHiroki Sato if (error) { 532268a55bcSHiroki Sato warnx("mdconfig (attach) error: file=%s", 533268a55bcSHiroki Sato vnodefile); 5341bf9e66cSXin LI free(vnodefile); 535268a55bcSHiroki Sato return (NULL); 536268a55bcSHiroki Sato } 537268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 538268a55bcSHiroki Sato if (sfd == NULL) { 539268a55bcSHiroki Sato warn("mdconfig (attach) fdopen error"); 540268a55bcSHiroki Sato ret = NULL; 541268a55bcSHiroki Sato goto err; 542268a55bcSHiroki Sato } 543268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 544268a55bcSHiroki Sato if (p == NULL && 545268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf))) { 546268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output"); 547268a55bcSHiroki Sato ret = NULL; 548268a55bcSHiroki Sato goto err; 549268a55bcSHiroki Sato } 550268a55bcSHiroki Sato strncpy(linebuf, p, linelen); 551268a55bcSHiroki Sato linebuf[linelen - 1] = '\0'; 552268a55bcSHiroki Sato errno = 0; 553268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 554268a55bcSHiroki Sato if (errno == 0) { 555268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 556268a55bcSHiroki Sato errno = EINVAL; 557268a55bcSHiroki Sato } 558268a55bcSHiroki Sato if (errno) { 559268a55bcSHiroki Sato warn("mdconfig (attach) unexpected output: %s", 560268a55bcSHiroki Sato linebuf); 561268a55bcSHiroki Sato ret = NULL; 562268a55bcSHiroki Sato goto err; 563268a55bcSHiroki Sato } 564268a55bcSHiroki Sato mdunit = (int)ul; 565268a55bcSHiroki Sato } else { 566268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 567268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 568268a55bcSHiroki Sato if (error == 0) { 569268a55bcSHiroki Sato /* md device found. Ignore it. */ 570268a55bcSHiroki Sato close(fd); 57179ba2f31SHiroki Sato if (qflag == 0) 572268a55bcSHiroki Sato warnx("md%d on %s: Device already " 573268a55bcSHiroki Sato "in use", mdunit, vnodefile); 5741bf9e66cSXin LI free(vnodefile); 575268a55bcSHiroki Sato return (NULL); 576268a55bcSHiroki Sato } 577268a55bcSHiroki Sato error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", 578268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit, vnodefile); 579268a55bcSHiroki Sato if (error) { 580268a55bcSHiroki Sato warnx("mdconfig (attach) error: " 581268a55bcSHiroki Sato "md%d on file=%s", mdunit, vnodefile); 5821bf9e66cSXin LI free(vnodefile); 583268a55bcSHiroki Sato return (NULL); 584268a55bcSHiroki Sato } 585268a55bcSHiroki Sato } 5868f8de1e1SXin LI } else /* SWAPOFF */ { 587268a55bcSHiroki Sato if (mdunit == -1) { 588268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s", 589268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile); 590268a55bcSHiroki Sato if (error) { 591268a55bcSHiroki Sato /* md device not found. Ignore it. */ 592268a55bcSHiroki Sato close(fd); 593268a55bcSHiroki Sato if (!qflag) 594268a55bcSHiroki Sato warnx("md on %s: Device not found", 595268a55bcSHiroki Sato vnodefile); 5961bf9e66cSXin LI free(vnodefile); 597268a55bcSHiroki Sato return (NULL); 598268a55bcSHiroki Sato } 599268a55bcSHiroki Sato sfd = fdopen(fd, "r"); 600268a55bcSHiroki Sato if (sfd == NULL) { 601268a55bcSHiroki Sato warn("mdconfig (list) fdopen error"); 602268a55bcSHiroki Sato ret = NULL; 603268a55bcSHiroki Sato goto err; 604268a55bcSHiroki Sato } 605268a55bcSHiroki Sato p = fgetln(sfd, &linelen); 606268a55bcSHiroki Sato if (p == NULL && 607268a55bcSHiroki Sato (linelen < 2 || linelen > sizeof(linebuf) - 1)) { 608268a55bcSHiroki Sato warn("mdconfig (list) unexpected output"); 609268a55bcSHiroki Sato ret = NULL; 610268a55bcSHiroki Sato goto err; 611268a55bcSHiroki Sato } 612268a55bcSHiroki Sato strncpy(linebuf, p, linelen); 613268a55bcSHiroki Sato linebuf[linelen - 1] = '\0'; 614268a55bcSHiroki Sato p = strchr(linebuf, ' '); 615268a55bcSHiroki Sato if (p != NULL) 616268a55bcSHiroki Sato *p = '\0'; 617268a55bcSHiroki Sato errno = 0; 618268a55bcSHiroki Sato ul = strtoul(linebuf, &p, 10); 619268a55bcSHiroki Sato if (errno == 0) { 620268a55bcSHiroki Sato if (*p != '\0' || ul > INT_MAX) 621268a55bcSHiroki Sato errno = EINVAL; 622268a55bcSHiroki Sato } 623268a55bcSHiroki Sato if (errno) { 624268a55bcSHiroki Sato warn("mdconfig (list) unexpected output: %s", 625268a55bcSHiroki Sato linebuf); 626268a55bcSHiroki Sato ret = NULL; 627268a55bcSHiroki Sato goto err; 628268a55bcSHiroki Sato } 629268a55bcSHiroki Sato mdunit = (int)ul; 630268a55bcSHiroki Sato } else { 631268a55bcSHiroki Sato error = run_cmd(&fd, "%s -l -n -f %s -u %d", 632268a55bcSHiroki Sato _PATH_MDCONFIG, vnodefile, mdunit); 633268a55bcSHiroki Sato if (error) { 634268a55bcSHiroki Sato /* md device not found. Ignore it. */ 635268a55bcSHiroki Sato close(fd); 636268a55bcSHiroki Sato if (!qflag) 637268a55bcSHiroki Sato warnx("md%d on %s: Device not found", 638268a55bcSHiroki Sato mdunit, vnodefile); 6391bf9e66cSXin LI free(vnodefile); 640268a55bcSHiroki Sato return (NULL); 641268a55bcSHiroki Sato } 642268a55bcSHiroki Sato } 643268a55bcSHiroki Sato } 644268a55bcSHiroki Sato snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, 645268a55bcSHiroki Sato MD_NAME, mdunit); 646268a55bcSHiroki Sato mdpath[sizeof(mdpath) - 1] = '\0'; 647268a55bcSHiroki Sato ret = swap_on_off_sfile(mdpath, doingall); 648268a55bcSHiroki Sato 6498f8de1e1SXin LI if (which_prog == SWAPOFF) { 650268a55bcSHiroki Sato if (ret != NULL) { 651268a55bcSHiroki Sato error = run_cmd(NULL, "%s -d -u %d", 652268a55bcSHiroki Sato _PATH_MDCONFIG, mdunit); 653268a55bcSHiroki Sato if (error) 654268a55bcSHiroki Sato warn("mdconfig (detach) detach failed: %s%s%d", 655268a55bcSHiroki Sato _PATH_DEV, MD_NAME, mdunit); 656268a55bcSHiroki Sato } 657268a55bcSHiroki Sato } 658268a55bcSHiroki Sato err: 659268a55bcSHiroki Sato if (sfd != NULL) 660268a55bcSHiroki Sato fclose(sfd); 661268a55bcSHiroki Sato if (fd != -1) 662268a55bcSHiroki Sato close(fd); 6631bf9e66cSXin LI free(vnodefile); 664268a55bcSHiroki Sato return (ret); 665268a55bcSHiroki Sato } 666268a55bcSHiroki Sato 667268a55bcSHiroki Sato static int 668268a55bcSHiroki Sato run_cmd(int *ofd, const char *cmdline, ...) 669268a55bcSHiroki Sato { 670268a55bcSHiroki Sato va_list ap; 671268a55bcSHiroki Sato char **argv, **argvp, *cmd, *p; 672268a55bcSHiroki Sato int argc, pid, status, rv; 673268a55bcSHiroki Sato int pfd[2], nfd, dup2dn; 674268a55bcSHiroki Sato 675268a55bcSHiroki Sato va_start(ap, cmdline); 676268a55bcSHiroki Sato rv = vasprintf(&cmd, cmdline, ap); 677268a55bcSHiroki Sato if (rv == -1) { 678268a55bcSHiroki Sato warn("%s", __func__); 67933c2e470SEnji Cooper va_end(ap); 680268a55bcSHiroki Sato return (rv); 681268a55bcSHiroki Sato } 682268a55bcSHiroki Sato va_end(ap); 683268a55bcSHiroki Sato 684268a55bcSHiroki Sato for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 685268a55bcSHiroki Sato argc++; 686268a55bcSHiroki Sato argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 687268a55bcSHiroki Sato for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 688268a55bcSHiroki Sato if (**argvp != '\0' && (++argvp > &argv[argc])) { 689268a55bcSHiroki Sato *argvp = NULL; 690268a55bcSHiroki Sato break; 691268a55bcSHiroki Sato } 692268a55bcSHiroki Sato /* The argv array ends up NULL-terminated here. */ 693268a55bcSHiroki Sato #if 0 694268a55bcSHiroki Sato { 695268a55bcSHiroki Sato int i; 696268a55bcSHiroki Sato 697268a55bcSHiroki Sato fprintf(stderr, "DEBUG: running:"); 698268a55bcSHiroki Sato /* Should be equivalent to 'cmd' (before strsep, of course). */ 699268a55bcSHiroki Sato for (i = 0; argv[i] != NULL; i++) 700268a55bcSHiroki Sato fprintf(stderr, " %s", argv[i]); 701268a55bcSHiroki Sato fprintf(stderr, "\n"); 702268a55bcSHiroki Sato } 703268a55bcSHiroki Sato #endif 704268a55bcSHiroki Sato dup2dn = 1; 705268a55bcSHiroki Sato if (ofd != NULL) { 706268a55bcSHiroki Sato if (pipe(&pfd[0]) == -1) { 707268a55bcSHiroki Sato warn("%s: pipe", __func__); 708268a55bcSHiroki Sato return (-1); 709268a55bcSHiroki Sato } 710268a55bcSHiroki Sato *ofd = pfd[0]; 711268a55bcSHiroki Sato dup2dn = 0; 712268a55bcSHiroki Sato } 713268a55bcSHiroki Sato pid = fork(); 714268a55bcSHiroki Sato switch (pid) { 715268a55bcSHiroki Sato case 0: 716268a55bcSHiroki Sato /* Child process. */ 717268a55bcSHiroki Sato if (ofd != NULL) 718268a55bcSHiroki Sato if (dup2(pfd[1], STDOUT_FILENO) < 0) 719268a55bcSHiroki Sato err(1, "dup2 in %s", __func__); 720268a55bcSHiroki Sato nfd = open(_PATH_DEVNULL, O_RDWR); 721268a55bcSHiroki Sato if (nfd == -1) 722268a55bcSHiroki Sato err(1, "%s: open %s", __func__, _PATH_DEVNULL); 723268a55bcSHiroki Sato if (dup2(nfd, STDIN_FILENO) < 0) 724268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 725268a55bcSHiroki Sato if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0) 726268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 727268a55bcSHiroki Sato if (dup2(nfd, STDERR_FILENO) < 0) 728268a55bcSHiroki Sato err(1, "%s: dup2", __func__); 729268a55bcSHiroki Sato execv(argv[0], argv); 730268a55bcSHiroki Sato warn("exec: %s", argv[0]); 731268a55bcSHiroki Sato _exit(-1); 732268a55bcSHiroki Sato case -1: 733268a55bcSHiroki Sato err(1, "%s: fork", __func__); 734268a55bcSHiroki Sato } 735268a55bcSHiroki Sato free(cmd); 736268a55bcSHiroki Sato free(argv); 737268a55bcSHiroki Sato while (waitpid(pid, &status, 0) != pid) 738268a55bcSHiroki Sato ; 739268a55bcSHiroki Sato return (WEXITSTATUS(status)); 740268a55bcSHiroki Sato } 741268a55bcSHiroki Sato 7426d5685c7SDoug Moore static int 7436d5685c7SDoug Moore swapon_trim(const char *name) 744a616b253SDoug Moore { 745a616b253SDoug Moore struct stat sb; 746a616b253SDoug Moore off_t ioarg[2], sz; 7476d5685c7SDoug Moore int error, fd; 748a616b253SDoug Moore 749*473fe2c0SDoug Moore /* Open a descriptor to create a consumer of the device. */ 750a616b253SDoug Moore fd = open(name, O_WRONLY); 751a616b253SDoug Moore if (fd < 0) 752a616b253SDoug Moore errx(1, "Cannot open %s", name); 753*473fe2c0SDoug Moore /* Find the device size. */ 754a616b253SDoug Moore if (fstat(fd, &sb) < 0) 755a616b253SDoug Moore errx(1, "Cannot stat %s", name); 756a616b253SDoug Moore if (S_ISREG(sb.st_mode)) 757a616b253SDoug Moore sz = sb.st_size; 7589035b225SDoug Moore else if (S_ISCHR(sb.st_mode)) { 759a616b253SDoug Moore if (ioctl(fd, DIOCGMEDIASIZE, &sz) != 0) 760a616b253SDoug Moore err(1, "ioctl(DIOCGMEDIASIZE)"); 761a616b253SDoug Moore } else 762a616b253SDoug Moore errx(1, "%s has an invalid file type", name); 763*473fe2c0SDoug Moore /* Trim the device. */ 764a616b253SDoug Moore ioarg[0] = 0; 765a616b253SDoug Moore ioarg[1] = sz; 766a616b253SDoug Moore if (ioctl(fd, DIOCGDELETE, ioarg) != 0) 767a616b253SDoug Moore warn("ioctl(DIOCGDELETE)"); 7686d5685c7SDoug Moore 769*473fe2c0SDoug Moore /* Start using the device for swapping, creating a second consumer. */ 7706d5685c7SDoug Moore error = swapon(name); 771*473fe2c0SDoug Moore 772*473fe2c0SDoug Moore /* 773*473fe2c0SDoug Moore * Do not close the device until the swap pager has attempted to create 774*473fe2c0SDoug Moore * another consumer. For GELI devices created with the 'detach -l' 775*473fe2c0SDoug Moore * option, removing the last consumer causes the device to be detached 776*473fe2c0SDoug Moore * - that is, to disappear. This ordering ensures that the device will 777*473fe2c0SDoug Moore * not be detached until swapoff is called. 778*473fe2c0SDoug Moore */ 779a616b253SDoug Moore close(fd); 7806d5685c7SDoug Moore return (error); 781a616b253SDoug Moore } 782a616b253SDoug Moore 783268a55bcSHiroki Sato static const char * 7848f8de1e1SXin LI swap_on_off_sfile(const char *name, int doingall) 785268a55bcSHiroki Sato { 786268a55bcSHiroki Sato int error; 787268a55bcSHiroki Sato 7886d5685c7SDoug Moore if (which_prog == SWAPON) 7896d5685c7SDoug Moore error = Eflag ? swapon_trim(name) : swapon(name); 7906d5685c7SDoug Moore else /* SWAPOFF */ 791268a55bcSHiroki Sato error = swapoff(name); 7928f8de1e1SXin LI 793268a55bcSHiroki Sato if (error == -1) { 7948fae3551SRodney W. Grimes switch (errno) { 7958fae3551SRodney W. Grimes case EBUSY: 79679ba2f31SHiroki Sato if (doingall == 0) 797268a55bcSHiroki Sato warnx("%s: Device already in use", name); 7988fae3551SRodney W. Grimes break; 7994937798dSDavid Schultz case EINVAL: 8004937798dSDavid Schultz if (which_prog == SWAPON) 8014937798dSDavid Schultz warnx("%s: NSWAPDEV limit reached", name); 80279ba2f31SHiroki Sato else if (doingall == 0) 8034937798dSDavid Schultz warn("%s", name); 8044937798dSDavid Schultz break; 8058fae3551SRodney W. Grimes default: 8066da7f378SPhilippe Charnier warn("%s", name); 8078fae3551SRodney W. Grimes break; 8088fae3551SRodney W. Grimes } 809268a55bcSHiroki Sato return (NULL); 8108fae3551SRodney W. Grimes } 811268a55bcSHiroki Sato return (name); 8128fae3551SRodney W. Grimes } 8138fae3551SRodney W. Grimes 8146da7f378SPhilippe Charnier static void 815a420c811SMatthew Dillon usage(void) 8168fae3551SRodney W. Grimes { 81779ba2f31SHiroki Sato 818a420c811SMatthew Dillon fprintf(stderr, "usage: %s ", getprogname()); 819a420c811SMatthew Dillon switch(orig_prog) { 820a420c811SMatthew Dillon case SWAPON: 821a616b253SDoug Moore fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n"); 822a616b253SDoug Moore break; 8238d646af5SRuslan Ermilov case SWAPOFF: 824268a55bcSHiroki Sato fprintf(stderr, "[-F fstab] -aLq | file ...\n"); 825a420c811SMatthew Dillon break; 826a420c811SMatthew Dillon case SWAPCTL: 8272e64768cSPawel Jakub Dawidek fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 828a420c811SMatthew Dillon break; 829a420c811SMatthew Dillon } 8308fae3551SRodney W. Grimes exit(1); 8318fae3551SRodney W. Grimes } 83292da00bbSMatthew Dillon 833a420c811SMatthew Dillon static void 8342e64768cSPawel Jakub Dawidek sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 8352e64768cSPawel Jakub Dawidek long blocksize) 8362e64768cSPawel Jakub Dawidek { 8372e64768cSPawel Jakub Dawidek char tmp[16]; 8382e64768cSPawel Jakub Dawidek 83979ba2f31SHiroki Sato if (hflag == 'H') { 8402e64768cSPawel Jakub Dawidek humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 8412e64768cSPawel Jakub Dawidek HN_B | HN_NOSPACE | HN_DECIMAL); 8422e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*s", hlen, tmp); 84379ba2f31SHiroki Sato } else 8442e64768cSPawel Jakub Dawidek snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 8452e64768cSPawel Jakub Dawidek } 8462e64768cSPawel Jakub Dawidek 8472e64768cSPawel Jakub Dawidek static void 848a420c811SMatthew Dillon swaplist(int lflag, int sflag, int hflag) 84992da00bbSMatthew Dillon { 850a420c811SMatthew Dillon size_t mibsize, size; 851a420c811SMatthew Dillon struct xswdev xsw; 85269095b02SMike Barcroft int hlen, mib[16], n, pagesize; 853a420c811SMatthew Dillon long blocksize; 854a420c811SMatthew Dillon long long total = 0; 855a420c811SMatthew Dillon long long used = 0; 856a420c811SMatthew Dillon long long tmp_total; 857a420c811SMatthew Dillon long long tmp_used; 8582e64768cSPawel Jakub Dawidek char buf[32]; 85992da00bbSMatthew Dillon 860a420c811SMatthew Dillon pagesize = getpagesize(); 861a420c811SMatthew Dillon switch(hflag) { 8622e64768cSPawel Jakub Dawidek case 'G': 8632e64768cSPawel Jakub Dawidek blocksize = 1024 * 1024 * 1024; 8642e64768cSPawel Jakub Dawidek strlcpy(buf, "1GB-blocks", sizeof(buf)); 8652e64768cSPawel Jakub Dawidek hlen = 10; 8662e64768cSPawel Jakub Dawidek break; 8672e64768cSPawel Jakub Dawidek case 'H': 8682e64768cSPawel Jakub Dawidek blocksize = -1; 8692e64768cSPawel Jakub Dawidek strlcpy(buf, "Bytes", sizeof(buf)); 8702e64768cSPawel Jakub Dawidek hlen = 10; 8712e64768cSPawel Jakub Dawidek break; 872a420c811SMatthew Dillon case 'K': 873a420c811SMatthew Dillon blocksize = 1024; 8742e64768cSPawel Jakub Dawidek strlcpy(buf, "1kB-blocks", sizeof(buf)); 875a420c811SMatthew Dillon hlen = 10; 876a420c811SMatthew Dillon break; 877a420c811SMatthew Dillon case 'M': 878a420c811SMatthew Dillon blocksize = 1024 * 1024; 8792e64768cSPawel Jakub Dawidek strlcpy(buf, "1MB-blocks", sizeof(buf)); 880a420c811SMatthew Dillon hlen = 10; 881a420c811SMatthew Dillon break; 882a420c811SMatthew Dillon default: 8839255f327SMike Barcroft getbsize(&hlen, &blocksize); 8842e64768cSPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 885a420c811SMatthew Dillon break; 88692da00bbSMatthew Dillon } 887a420c811SMatthew Dillon 88879ba2f31SHiroki Sato mibsize = nitems(mib); 889a420c811SMatthew Dillon if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 890a420c811SMatthew Dillon err(1, "sysctlnametomib()"); 891a420c811SMatthew Dillon 892a420c811SMatthew Dillon if (lflag) { 893a420c811SMatthew Dillon printf("%-13s %*s %*s\n", 894a420c811SMatthew Dillon "Device:", 895a420c811SMatthew Dillon hlen, buf, 896a420c811SMatthew Dillon hlen, "Used:"); 897a420c811SMatthew Dillon } 898a420c811SMatthew Dillon 899a420c811SMatthew Dillon for (n = 0; ; ++n) { 900a420c811SMatthew Dillon mib[mibsize] = n; 901a420c811SMatthew Dillon size = sizeof xsw; 90216fc3635SMark Murray if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 903a420c811SMatthew Dillon break; 904a420c811SMatthew Dillon if (xsw.xsw_version != XSWDEV_VERSION) 905a420c811SMatthew Dillon errx(1, "xswdev version mismatch"); 906a420c811SMatthew Dillon 9072e64768cSPawel Jakub Dawidek tmp_total = (long long)xsw.xsw_nblks * pagesize; 9082e64768cSPawel Jakub Dawidek tmp_used = (long long)xsw.xsw_used * pagesize; 909a420c811SMatthew Dillon total += tmp_total; 910a420c811SMatthew Dillon used += tmp_used; 911a420c811SMatthew Dillon if (lflag) { 9122e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 9132e64768cSPawel Jakub Dawidek blocksize); 9142e64768cSPawel Jakub Dawidek printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 9152e64768cSPawel Jakub Dawidek buf); 9162e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 9172e64768cSPawel Jakub Dawidek blocksize); 9182e64768cSPawel Jakub Dawidek printf("%s\n", buf); 919a420c811SMatthew Dillon } 920a420c811SMatthew Dillon } 921a420c811SMatthew Dillon if (errno != ENOENT) 922a420c811SMatthew Dillon err(1, "sysctl()"); 923a420c811SMatthew Dillon 924a420c811SMatthew Dillon if (sflag) { 9252e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 9262e64768cSPawel Jakub Dawidek printf("Total: %s ", buf); 9272e64768cSPawel Jakub Dawidek sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 9282e64768cSPawel Jakub Dawidek printf("%s\n", buf); 929a420c811SMatthew Dillon } 930a420c811SMatthew Dillon } 931a420c811SMatthew Dillon 932