1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1980, 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 * Copyright (c) 2017 Yoshihiro Ota
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34
35__FBSDID("$FreeBSD$");
36
37#ifdef lint
38static const char sccsid[] = "@(#)swap.c	8.3 (Berkeley) 4/29/95";
39#endif
40
41/*
42 * swapinfo - based on a program of the same name by Kevin Lahey
43 */
44
45#include <sys/param.h>
46#include <sys/ioctl.h>
47#include <sys/stat.h>
48
49#include <kvm.h>
50#include <nlist.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <unistd.h>
54#include <string.h>
55#include <err.h>
56
57#include "systat.h"
58#include "extern.h"
59#include "devs.h"
60
61static char *header;
62static long blocksize;
63static int dlen, odlen;
64static int hlen;
65static int ulen, oulen;
66static int pagesize;
67
68WINDOW *
69openswap(void)
70{
71	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
72}
73
74void
75closeswap(WINDOW *w)
76{
77	if (w == NULL)
78		return;
79	wclear(w);
80	wrefresh(w);
81	delwin(w);
82}
83
84/*
85 * The meat of all the swap stuff is stolen from pstat(8)'s
86 * swapmode(), which is based on a program called swapinfo written by
87 * Kevin Lahey <kml@rokkaku.atl.ga.us>.
88 */
89
90#define NSWAP	16
91
92static struct kvm_swap kvmsw[NSWAP];
93static int kvnsw, okvnsw;
94
95static void calclens(void);
96
97#define CONVERT(v)	((int)((int64_t)(v) * pagesize / blocksize))
98
99static void
100calclens(void)
101{
102	int i, n;
103	int len;
104
105	dlen = sizeof("Disk");
106	for (i = 0; i < kvnsw; ++i) {
107		len = strlen(kvmsw[i].ksw_devname);
108		if (dlen < len)
109			dlen = len;
110	}
111
112	ulen = sizeof("Used");
113	for (n = CONVERT(kvmsw[kvnsw].ksw_used), len = 2; n /= 10; ++len);
114	if (ulen < len)
115		ulen = len;
116}
117
118int
119initswap(void)
120{
121	static int once = 0;
122
123	if (once)
124		return (1);
125
126	header = getbsize(&hlen, &blocksize);
127	pagesize = getpagesize();
128
129	if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) {
130		error("systat: kvm_getswapinfo failed");
131		return (0);
132	}
133	okvnsw = kvnsw;
134
135	calclens();
136	odlen = dlen;
137	oulen = ulen;
138
139	once = 1;
140
141	dsinit(12);
142
143	return (1);
144}
145
146void
147fetchswap(void)
148{
149	okvnsw = kvnsw;
150	if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) {
151		error("systat: kvm_getswapinfo failed");
152		return;
153	}
154
155	odlen = dlen;
156	oulen = ulen;
157	calclens();
158
159	struct devinfo *tmp_dinfo;
160
161	tmp_dinfo = last_dev.dinfo;
162	last_dev.dinfo = cur_dev.dinfo;
163	cur_dev.dinfo = tmp_dinfo;
164
165	last_dev.snap_time = cur_dev.snap_time;
166	dsgetinfo( &cur_dev );
167}
168
169void
170labelswap(void)
171{
172	const char *name;
173	int i;
174
175	fetchswap();
176
177	werase(wnd);
178
179	mvwprintw(wnd, 0, 0, "%*s%*s%*s %s",
180	    -dlen, "Disk", hlen, header, ulen, "Used",
181	    "/0%  /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
182
183	for (i = 0; i <= kvnsw; ++i) {
184		if (i == kvnsw) {
185			if (kvnsw == 1)
186				break;
187			name = "Total";
188		} else
189			name = kvmsw[i].ksw_devname;
190		mvwprintw(wnd, i + 1, 0, "%*s", -dlen, name);
191	}
192	dslabel(12, 0, 18);
193}
194
195void
196showswap(void)
197{
198	int count;
199	int i;
200
201	if (kvnsw != okvnsw || dlen != odlen || ulen != oulen)
202		labelswap();
203
204	for (i = 0; i <= kvnsw; ++i) {
205		if (i == kvnsw) {
206			if (kvnsw == 1)
207				break;
208		}
209
210		if (kvmsw[i].ksw_total == 0) {
211			mvwprintw(
212			    wnd,
213			    i + 1,
214			    dlen + hlen + ulen + 1,
215			    "(swap not configured)"
216			);
217			continue;
218		}
219
220		wmove(wnd, i + 1, dlen);
221
222		wprintw(wnd, "%*d", hlen, CONVERT(kvmsw[i].ksw_total));
223		wprintw(wnd, "%*d", ulen, CONVERT(kvmsw[i].ksw_used));
224
225		count = 50.0 * kvmsw[i].ksw_used / kvmsw[i].ksw_total + 1;
226
227		waddch(wnd, ' ');
228		while (count--)
229			waddch(wnd, 'X');
230		wclrtoeol(wnd);
231	}
232	dsshow(12, 0, 18, &cur_dev, &last_dev);
233}
234