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