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