swapon(8): Fix "swapctl -l".
[dragonfly.git] / sbin / swapon / swapon.c
CommitLineData
984263bc
MD
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.
1de703da
MD
32 *
33 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)swapon.c 8.1 (Berkeley) 6/5/93
35 * $FreeBSD: src/sbin/swapon/swapon.c,v 1.8.2.2 2001/07/30 10:30:11 dd Exp $
984263bc
MD
36 */
37
9f3543c6
MD
38#include <sys/param.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <vm/vm_param.h>
42
984263bc
MD
43#include <err.h>
44#include <errno.h>
45#include <fstab.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
9f3543c6
MD
50#include <fcntl.h>
51#include <libutil.h>
984263bc 52
9a76cd75 53static void usage(void);
9f3543c6
MD
54static int swap_on_off(char *name, int doingall);
55static void swaplist(int lflag, int sflag, int hflag);
56
57enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
984263bc
MD
58
59int
60main(int argc, char **argv)
61{
b942f274 62 struct fstab *fsp;
9f3543c6
MD
63 char *ptr;
64 int ret;
65 int ch;
66 int doall, sflag, lflag, hflag, qflag;
984263bc 67
9f3543c6
MD
68 if ((ptr = strrchr(argv[0], '/')) == NULL)
69 ptr = argv[0];
70 if (strstr(ptr, "swapon"))
71 which_prog = SWAPON;
72 else if (strstr(ptr, "swapoff"))
73 which_prog = SWAPOFF;
74 orig_prog = which_prog;
75
76 sflag = lflag = hflag = qflag = doall = 0;
77 while ((ch = getopt(argc, argv, "AadghklmqsU")) != -1) {
984263bc 78 switch((char)ch) {
9f3543c6
MD
79 case 'A':
80 if (which_prog == SWAPCTL) {
81 doall = 1;
82 which_prog = SWAPON;
83 } else {
84 usage();
85 }
86 break;
984263bc 87 case 'a':
9f3543c6
MD
88 if (which_prog == SWAPON || which_prog == SWAPOFF)
89 doall = 1;
90 else
91 which_prog = SWAPON;
92 break;
93 case 'd':
94 if (which_prog == SWAPCTL)
95 which_prog = SWAPOFF;
96 else
97 usage();
98 break;
99 case 'g':
100 hflag = 'G';
101 break;
102 case 'h':
103 hflag = 'H';
104 break;
105 case 'k':
106 hflag = 'K';
107 break;
108 case 'l':
109 lflag = 1;
110 break;
111 case 'm':
112 hflag = 'M';
113 break;
114 case 'q':
115 if (which_prog == SWAPON || which_prog == SWAPOFF)
116 qflag = 1;
117 break;
118 case 's':
119 sflag = 1;
120 break;
121 case 'U':
122 if (which_prog == SWAPCTL) {
123 doall = 1;
124 which_prog = SWAPOFF;
125 } else {
126 usage();
127 }
984263bc
MD
128 break;
129 case '?':
130 default:
131 usage();
132 }
9f3543c6 133 }
984263bc
MD
134 argv += optind;
135
9f3543c6
MD
136 ret = 0;
137 if (which_prog == SWAPON || which_prog == SWAPOFF) {
138 if (doall) {
139 while ((fsp = getfsent()) != NULL) {
140 if (strcmp(fsp->fs_type, FSTAB_SW))
141 continue;
142 if (strstr(fsp->fs_mntops, "noauto"))
143 continue;
144 if (swap_on_off(fsp->fs_spec, 1)) {
145 ret = 1;
146 } else {
147 if (!qflag) {
148 printf("%s: %sing %s as swap device\n",
149 getprogname(),
150 which_prog == SWAPOFF ? "remov" : "add",
151 fsp->fs_spec);
152 }
153 }
154 }
155 } else if (*argv == NULL) {
156 usage();
984263bc 157 }
9f3543c6
MD
158 for (; *argv; ++argv) {
159 if (swap_on_off(getdevpath(*argv, 0), 0)) {
160 ret = 1;
161 } else if (orig_prog == SWAPCTL) {
162 printf("%s: %sing %s as swap device\n",
163 getprogname(),
164 which_prog == SWAPOFF ? "remov" : "add",
165 *argv);
166 }
167 }
168 } else {
169 if (lflag || sflag)
170 swaplist(lflag, sflag, hflag);
171 else
172 usage();
c4d5a9b3 173 }
9f3543c6 174 exit(ret);
984263bc
MD
175}
176
9f3543c6
MD
177static int
178swap_on_off(char *name, int doingall)
984263bc 179{
9f3543c6
MD
180 if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
181 switch(errno) {
984263bc 182 case EBUSY:
9f3543c6 183 if (!doingall)
984263bc
MD
184 warnx("%s: device already in use", name);
185 break;
9f3543c6
MD
186 case EINVAL:
187 if (which_prog == SWAPON)
188 warnx("%s: NSWAPDEV limit reached", name);
189 else if (!doingall)
190 warn("%s", name);
191 break;
984263bc
MD
192 default:
193 warn("%s", name);
194 break;
195 }
196 return(1);
197 }
198 return(0);
199}
200
201static void
b5744197 202usage(void)
984263bc 203{
9f3543c6
MD
204 fprintf(stderr, "usage: %s ", getprogname());
205 switch (orig_prog) {
206 case SWAPON:
207 case SWAPOFF:
208 fprintf(stderr, "-aq | file ...\n");
209 break;
210 case SWAPCTL:
211 fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n");
212 break;
213 }
984263bc
MD
214 exit(1);
215}
9f3543c6
MD
216
217static void
218sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen,
219 long blocksize)
220{
221 if (hflag == 'H') {
222 char tmp[16];
223
224 humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE,
225 HN_B | HN_NOSPACE | HN_DECIMAL);
226 snprintf(buf, bufsize, "%*s", hlen, tmp);
227 } else {
228 snprintf(buf, bufsize, "%*lld", hlen, val / blocksize);
229 }
230}
231
232static void
233swaplist(int lflag, int sflag, int hflag)
234{
235 size_t ksize, bytes = 0;
236 char *xswbuf;
237 struct xswdev *xsw;
238 int hlen, pagesize;
239 int i, n;
240 long blocksize;
241 long long total, used, tmp_total, tmp_used;
242 char buf[32];
243
244 pagesize = getpagesize();
245 switch(hflag) {
246 case 'G':
247 blocksize = 1024 * 1024 * 1024;
248 strlcpy(buf, "1GB-blocks", sizeof(buf));
249 hlen = 10;
250 break;
251 case 'H':
252 blocksize = -1;
253 strlcpy(buf, "Bytes", sizeof(buf));
254 hlen = 10;
255 break;
256 case 'K':
257 blocksize = 1024;
258 strlcpy(buf, "1kB-blocks", sizeof(buf));
259 hlen = 10;
260 break;
261 case 'M':
262 blocksize = 1024 * 1024;
263 strlcpy(buf, "1MB-blocks", sizeof(buf));
264 hlen = 10;
265 break;
266 default:
267 getbsize(&hlen, &blocksize);
268 snprintf(buf, sizeof(buf), "%ld-blocks", blocksize);
269 break;
270 }
271
272 if (sysctlbyname("vm.swap_info_array", NULL, &bytes, NULL, 0) < 0)
273 err(1, "sysctlbyname()");
274 if (bytes == 0)
275 err(1, "sysctlbyname()");
276
277 xswbuf = malloc(bytes);
278 if (sysctlbyname("vm.swap_info_array", xswbuf, &bytes, NULL, 0) < 0) {
279 free(xswbuf);
280 err(1, "sysctlbyname()");
281 }
282 if (bytes == 0) {
283 free(xswbuf);
284 err(1, "sysctlbyname()");
285 }
286
287 /*
288 * Calculate size of xsw entry returned by kernel (it can be larger
289 * than the one we have if there is a version mismatch).
290 */
291 ksize = ((struct xswdev *)xswbuf)->xsw_size;
292 n = (int)(bytes / ksize);
293
294 if (lflag) {
295 printf("%-13s %*s %*s\n",
296 "Device:",
297 hlen, buf,
298 hlen, "Used:");
299 }
300
301 total = used = tmp_total = tmp_used = 0;
302 for (i = 0; i < n; ++i) {
303 xsw = (void *)((char *)xswbuf + i * ksize);
304
305 if (xsw->xsw_nblks == 0)
306 continue;
307
ebd20800
SW
308 tmp_total = (long long)xsw->xsw_nblks * pagesize;
309 tmp_used = (long long)xsw->xsw_used * pagesize;
310 total += tmp_total;
311 used += tmp_used;
9f3543c6
MD
312 if (lflag) {
313 sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen,
314 blocksize);
315 if (xsw->xsw_dev == NODEV) {
316 printf("%-13s %s ", "[NFS swap]", buf);
317 } else {
318 printf("/dev/%-8s %s ",
319 devname(xsw->xsw_dev, S_IFCHR), buf);
320 }
321
322 sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen,
323 blocksize);
324 printf("%s\n", buf);
325 }
326 }
327
328 if (sflag) {
329 sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize);
330 printf("Total: %s ", buf);
331 sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize);
332 printf("%s\n", buf);
333 }
334}