swapon.c revision 108459
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 108459 2002-12-30 18:24:14Z mike $";
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 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, NULL) == -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