1efd4c9b6SSteve Lawrence /*
2efd4c9b6SSteve Lawrence  * CDDL HEADER START
3efd4c9b6SSteve Lawrence  *
4efd4c9b6SSteve Lawrence  * The contents of this file are subject to the terms of the
5efd4c9b6SSteve Lawrence  * Common Development and Distribution License (the "License").
6efd4c9b6SSteve Lawrence  * You may not use this file except in compliance with the License.
7efd4c9b6SSteve Lawrence  *
8efd4c9b6SSteve Lawrence  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9efd4c9b6SSteve Lawrence  * or http://www.opensolaris.org/os/licensing.
10efd4c9b6SSteve Lawrence  * See the License for the specific language governing permissions
11efd4c9b6SSteve Lawrence  * and limitations under the License.
12efd4c9b6SSteve Lawrence  *
13efd4c9b6SSteve Lawrence  * When distributing Covered Code, include this CDDL HEADER in each
14efd4c9b6SSteve Lawrence  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15efd4c9b6SSteve Lawrence  * If applicable, add the following below this CDDL HEADER, with the
16efd4c9b6SSteve Lawrence  * fields enclosed by brackets "[]" replaced with your own identifying
17efd4c9b6SSteve Lawrence  * information: Portions Copyright [yyyy] [name of copyright owner]
18efd4c9b6SSteve Lawrence  *
19efd4c9b6SSteve Lawrence  * CDDL HEADER END
20efd4c9b6SSteve Lawrence  */
21efd4c9b6SSteve Lawrence 
22efd4c9b6SSteve Lawrence /*
23efd4c9b6SSteve Lawrence  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24efd4c9b6SSteve Lawrence  */
25efd4c9b6SSteve Lawrence 
26efd4c9b6SSteve Lawrence #include <alloca.h>
27efd4c9b6SSteve Lawrence #include <assert.h>
28efd4c9b6SSteve Lawrence #include <errno.h>
29efd4c9b6SSteve Lawrence #include <langinfo.h>
30efd4c9b6SSteve Lawrence #include <libintl.h>
31efd4c9b6SSteve Lawrence #include <libscf.h>
32efd4c9b6SSteve Lawrence #include <signal.h>
33efd4c9b6SSteve Lawrence #include <stdarg.h>
34efd4c9b6SSteve Lawrence #include <stdio.h>
35efd4c9b6SSteve Lawrence #include <stdlib.h>
36efd4c9b6SSteve Lawrence #include <strings.h>
37efd4c9b6SSteve Lawrence #include <sys/fxpriocntl.h>
38efd4c9b6SSteve Lawrence #include <sys/priocntl.h>
39efd4c9b6SSteve Lawrence #include <sys/types.h>
40efd4c9b6SSteve Lawrence #include <time.h>
41efd4c9b6SSteve Lawrence #include <unistd.h>
42efd4c9b6SSteve Lawrence #include <zonestat.h>
43efd4c9b6SSteve Lawrence 
44efd4c9b6SSteve Lawrence extern char *optarg;
45efd4c9b6SSteve Lawrence extern int optind, opterr, optopt;
46efd4c9b6SSteve Lawrence 
47efd4c9b6SSteve Lawrence #define	ZSTAT_OK		0
48efd4c9b6SSteve Lawrence #define	ZSTAT_ERROR		1
49efd4c9b6SSteve Lawrence #define	ZSTAT_USAGE		2
50efd4c9b6SSteve Lawrence 
51efd4c9b6SSteve Lawrence #define	ZSTAT_UNIX_TIMESTAMP	1
52efd4c9b6SSteve Lawrence #define	ZSTAT_ISO_TIMESTAMP	2
53efd4c9b6SSteve Lawrence #define	ZSTAT_DATE_TIMESTAMP	3
54efd4c9b6SSteve Lawrence 
55efd4c9b6SSteve Lawrence #define	ZSTAT_RES_PHYSICAL_MEMORY	0x1
56efd4c9b6SSteve Lawrence #define	ZSTAT_RES_VIRTUAL_MEMORY	0x2
57efd4c9b6SSteve Lawrence #define	ZSTAT_RES_LOCKED_MEMORY		0x4
58efd4c9b6SSteve Lawrence #define	ZSTAT_RES_MEMORY		0x7
59efd4c9b6SSteve Lawrence 
60efd4c9b6SSteve Lawrence #define	ZSTAT_RES_DEFAULT_PSET		0x10
61efd4c9b6SSteve Lawrence #define	ZSTAT_RES_PSETS			0x20
62efd4c9b6SSteve Lawrence #define	ZSTAT_RES_SUMMARY		0x40
63efd4c9b6SSteve Lawrence 
64efd4c9b6SSteve Lawrence #define	ZSTAT_RES_PROCESSES		0x100
65efd4c9b6SSteve Lawrence #define	ZSTAT_RES_LWPS			0x200
66efd4c9b6SSteve Lawrence #define	ZSTAT_RES_LOFI			0x400
67efd4c9b6SSteve Lawrence #define	ZSTAT_RES_LIMITS		0x700
68efd4c9b6SSteve Lawrence 
69efd4c9b6SSteve Lawrence #define	ZSTAT_RES_SHM_MEMORY		0x1000
70efd4c9b6SSteve Lawrence #define	ZSTAT_RES_SHM_IDS		0x2000
71efd4c9b6SSteve Lawrence #define	ZSTAT_RES_SEM_IDS		0x4000
72efd4c9b6SSteve Lawrence #define	ZSTAT_RES_MSG_IDS		0x8000
73efd4c9b6SSteve Lawrence #define	ZSTAT_RES_SYSV			0xF000
74efd4c9b6SSteve Lawrence 
75efd4c9b6SSteve Lawrence #define	ZSTAT_RES_ALL			0xF777
76efd4c9b6SSteve Lawrence 
77efd4c9b6SSteve Lawrence #define	ZONESTAT_PHYSICAL_MEMORY	"physical-memory"
78efd4c9b6SSteve Lawrence #define	ZONESTAT_VIRTUAL_MEMORY		"virtual-memory"
79efd4c9b6SSteve Lawrence #define	ZONESTAT_LOCKED_MEMORY		"locked-memory"
80efd4c9b6SSteve Lawrence #define	ZONESTAT_MEMORY			"memory"
81efd4c9b6SSteve Lawrence 
82efd4c9b6SSteve Lawrence #define	ZONESTAT_DEFAULT_PSET		"default-pset"
83efd4c9b6SSteve Lawrence #define	ZONESTAT_POOL_PSET		"pool-pset"
84efd4c9b6SSteve Lawrence #define	ZONESTAT_PSRSET_PSET		"psrset-pset"
85efd4c9b6SSteve Lawrence #define	ZONESTAT_DEDICATED_CPU		"dedicated-cpu"
86efd4c9b6SSteve Lawrence #define	ZONESTAT_PROCESSOR_SET		"processor-set"
87efd4c9b6SSteve Lawrence #define	ZONESTAT_PSETS			"psets"
88efd4c9b6SSteve Lawrence #define	ZONESTAT_SUMMARY		"summary"
89efd4c9b6SSteve Lawrence 
90efd4c9b6SSteve Lawrence #define	ZONESTAT_PROCESSES		"processes"
91efd4c9b6SSteve Lawrence #define	ZONESTAT_LWPS			"lwps"
92efd4c9b6SSteve Lawrence #define	ZONESTAT_LOFI			"lofi"
93efd4c9b6SSteve Lawrence #define	ZONESTAT_LIMITS			"limits"
94efd4c9b6SSteve Lawrence 
95efd4c9b6SSteve Lawrence #define	ZONESTAT_SHM_MEMORY		"shm-memory"
96efd4c9b6SSteve Lawrence #define	ZONESTAT_SHM_IDS		"shm-ids"
97efd4c9b6SSteve Lawrence #define	ZONESTAT_SEM_IDS		"sem-ids"
98efd4c9b6SSteve Lawrence #define	ZONESTAT_MSG_IDS		"msg-ids"
99efd4c9b6SSteve Lawrence #define	ZONESTAT_SYSV			"sysv"
100efd4c9b6SSteve Lawrence 
101efd4c9b6SSteve Lawrence #define	ZONESTAT_ALL			"all"
102efd4c9b6SSteve Lawrence 
103efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_MEM_DEFAULT	"mem_default"
104efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_VM_DEFAULT	"vm_default"
105efd4c9b6SSteve Lawrence 
106efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_AVERAGE		"average"
107efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_HIGH		"high"
108efd4c9b6SSteve Lawrence 
109efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_RESOURCE		"resource"
110efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_TOTAL		"total"
111efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_SYSTEM		"system"
112efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_ZONES		"zones"
113efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_HEADER		"header"
114efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_FOOTER		"footer"
115efd4c9b6SSteve Lawrence 
116efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_NAME		"name"
117efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_USED		"used"
118efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_CAP		"cap"
119efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_PCAP		"pcap"
120efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_SHR		"shr"
121efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_PSHRU		"pshru"
122efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_CPU		"cpu"
125efd4c9b6SSteve Lawrence 
126efd4c9b6SSteve Lawrence #define	ZONESTAT_NAME_SYSTEM_LIMIT	"system-limit"
127efd4c9b6SSteve Lawrence 
128efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_FMT_INTERVAL	0
129efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_FMT_TOTAL		1
130efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_FMT_AVERAGE	2
131efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_FMT_HIGH		3
132efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_FMT_END		4
133efd4c9b6SSteve Lawrence 
134efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_TEXT_INTERVAL	"interval"
135efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_TEXT_TOTAL		"report-total"
136efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_TEXT_AVERAGE	"report-average"
137efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_TEXT_HIGH		"report-high"
138efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_TEXT_END		"footer"
139efd4c9b6SSteve Lawrence 
140efd4c9b6SSteve Lawrence #define	ZSTAT_DURATION_INF	((int)INT_MAX)
141efd4c9b6SSteve Lawrence #define	ZSTAT_INTERVAL_DEFAULT	((int)INT_MAX)
142efd4c9b6SSteve Lawrence #define	ZSTAT_REPORT_END	((int)INT_MAX)
143efd4c9b6SSteve Lawrence 
144efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_CPU		1
145efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_PHYSICAL	2
146efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_VIRTUAL	3
147efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_USED		4
148efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_CAP		5
149efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_PCAP		6
150efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_SHR		7
151efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_PSHRU	8
152efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_NAME		9
153efd4c9b6SSteve Lawrence #define	ZSTAT_SORT_MAX		10
154efd4c9b6SSteve Lawrence 
155efd4c9b6SSteve Lawrence #define	ZSTAT_SUM_MIN_ZONENAME 19
156efd4c9b6SSteve Lawrence #define	ZSTAT_SUM_HDR_FORMAT "%23s %17s %17s\n"
157efd4c9b6SSteve Lawrence #define	ZSTAT_SUM_ZONE_FORMAT "%5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n"
158efd4c9b6SSteve Lawrence 
159efd4c9b6SSteve Lawrence #define	ZSTAT_CPU_MIN_PSETNAME 22
160efd4c9b6SSteve Lawrence #define	ZSTAT_CPU_MIN_ZONENAME 36
161efd4c9b6SSteve Lawrence #define	ZSTAT_CPU_RES_FORMAT "%13s  %11s %11s\n"
162efd4c9b6SSteve Lawrence #define	ZSTAT_CPU_ZONE_FORMAT "%5s %5s %5s %5s %6s %5s %5s\n"
163efd4c9b6SSteve Lawrence 
164efd4c9b6SSteve Lawrence #define	ZSTAT_RESOURCE_MIN_RESNAME 28
165efd4c9b6SSteve Lawrence #define	ZSTAT_RESOURCE_MIN_ZONENAME 36
166efd4c9b6SSteve Lawrence #define	ZSTAT_RESOURCE_FORMAT "%13s\n"
167efd4c9b6SSteve Lawrence #define	ZSTAT_RESOURCE_ZONE_FORMAT "%5s %5s %5s %5s\n"
168efd4c9b6SSteve Lawrence 
169efd4c9b6SSteve Lawrence #define	ZS_UINT64_STRLEN 20
170efd4c9b6SSteve Lawrence #define	ZS_PCT_STRLEN	10
171efd4c9b6SSteve Lawrence #define	ZS_TIME_STRLEN	20
172efd4c9b6SSteve Lawrence #define	ZS_NAME_STRLEN	10
173efd4c9b6SSteve Lawrence 
174efd4c9b6SSteve Lawrence time_t g_now_time;
175efd4c9b6SSteve Lawrence time_t g_boot_time;
176efd4c9b6SSteve Lawrence time_t g_start_time;
177efd4c9b6SSteve Lawrence time_t g_end_time;
178efd4c9b6SSteve Lawrence int g_interval;
179efd4c9b6SSteve Lawrence int g_count;
180efd4c9b6SSteve Lawrence int g_report_count;
181efd4c9b6SSteve Lawrence time_t g_seconds;
182efd4c9b6SSteve Lawrence 
183efd4c9b6SSteve Lawrence int g_resources;
184efd4c9b6SSteve Lawrence zs_ctl_t *g_zsctl;
185efd4c9b6SSteve Lawrence boolean_t g_quit = B_FALSE;
186efd4c9b6SSteve Lawrence zs_zone_t **g_zone_list;
187efd4c9b6SSteve Lawrence int g_zone_num;
188efd4c9b6SSteve Lawrence zs_pset_zone_t **g_pz_list;
189efd4c9b6SSteve Lawrence int g_pz_num;
190efd4c9b6SSteve Lawrence zs_pset_t **g_pset_list;
191efd4c9b6SSteve Lawrence int g_pset_num;
192efd4c9b6SSteve Lawrence int g_sort_by;
193efd4c9b6SSteve Lawrence int g_sorts[ZSTAT_SORT_MAX];
194efd4c9b6SSteve Lawrence int g_sort_summary;
195efd4c9b6SSteve Lawrence size_t g_max_zonename;
196efd4c9b6SSteve Lawrence 
197efd4c9b6SSteve Lawrence /* Storage for command line arguments. */
198efd4c9b6SSteve Lawrence char **arg_zonenames;
199efd4c9b6SSteve Lawrence int arg_zonename_count;
200efd4c9b6SSteve Lawrence char **arg_resnames;
201efd4c9b6SSteve Lawrence int arg_resname_count;
202efd4c9b6SSteve Lawrence char **arg_restypes;
203efd4c9b6SSteve Lawrence int arg_restype_count;
204efd4c9b6SSteve Lawrence char ** arg_reports;
205efd4c9b6SSteve Lawrence int arg_report_count;
206efd4c9b6SSteve Lawrence char ** arg_sort_list;
207efd4c9b6SSteve Lawrence int arg_sort_count;
208efd4c9b6SSteve Lawrence char ** arg_line_list;
209efd4c9b6SSteve Lawrence int arg_line_count;
210efd4c9b6SSteve Lawrence 
211efd4c9b6SSteve Lawrence time_t arg_starttime;
212efd4c9b6SSteve Lawrence time_t arg_endtime;
213efd4c9b6SSteve Lawrence uint_t arg_timestamp = ZSTAT_DATE_TIMESTAMP;
214efd4c9b6SSteve Lawrence int arg_interval = 5;
215efd4c9b6SSteve Lawrence int arg_duration = -1;
216efd4c9b6SSteve Lawrence int arg_report = -1;
217efd4c9b6SSteve Lawrence 
218efd4c9b6SSteve Lawrence /* Options with or as arguments */
219efd4c9b6SSteve Lawrence boolean_t opt_zonenames = B_FALSE;
220efd4c9b6SSteve Lawrence boolean_t opt_resnames = B_FALSE;
221efd4c9b6SSteve Lawrence boolean_t opt_restypes = B_FALSE;
222efd4c9b6SSteve Lawrence boolean_t opt_start = B_FALSE;
223efd4c9b6SSteve Lawrence boolean_t opt_end = B_FALSE;
224efd4c9b6SSteve Lawrence boolean_t opt_in = B_FALSE;
225efd4c9b6SSteve Lawrence boolean_t opt_out = B_FALSE;
226efd4c9b6SSteve Lawrence boolean_t opt_timestamp = B_FALSE;
227efd4c9b6SSteve Lawrence boolean_t opt_report = B_FALSE;
228efd4c9b6SSteve Lawrence boolean_t opt_sort = B_FALSE;
229efd4c9b6SSteve Lawrence 
230efd4c9b6SSteve Lawrence boolean_t opt_report_high = B_FALSE;
231efd4c9b6SSteve Lawrence boolean_t opt_report_total = B_FALSE;
232efd4c9b6SSteve Lawrence boolean_t opt_report_average = B_FALSE;
233efd4c9b6SSteve Lawrence 
234efd4c9b6SSteve Lawrence boolean_t opt_line_resource = B_FALSE;
235efd4c9b6SSteve Lawrence boolean_t opt_line_total = B_FALSE;
236efd4c9b6SSteve Lawrence boolean_t opt_line_system = B_FALSE;
237efd4c9b6SSteve Lawrence boolean_t opt_line_zones = B_FALSE;
238efd4c9b6SSteve Lawrence boolean_t opt_line_header = B_FALSE;
239efd4c9b6SSteve Lawrence boolean_t opt_line_any = B_FALSE;
240efd4c9b6SSteve Lawrence 
241efd4c9b6SSteve Lawrence /* Options without arguments */
242efd4c9b6SSteve Lawrence boolean_t opt_quiet_intervals = B_FALSE;
243efd4c9b6SSteve Lawrence boolean_t opt_parseable = B_FALSE;
244efd4c9b6SSteve Lawrence boolean_t opt_debug = B_FALSE;
245efd4c9b6SSteve Lawrence 
246efd4c9b6SSteve Lawrence static int
zonestat_usage(boolean_t explicit)247efd4c9b6SSteve Lawrence zonestat_usage(boolean_t explicit)
248efd4c9b6SSteve Lawrence {
249efd4c9b6SSteve Lawrence 	FILE *fd = explicit ? stdout : stderr;
250efd4c9b6SSteve Lawrence 
251efd4c9b6SSteve Lawrence 	(void) fprintf(fd, gettext("Usage:\n"));
252efd4c9b6SSteve Lawrence 	(void) fprintf(fd,
253efd4c9b6SSteve Lawrence "    zonestat [-z zonelist] [-r reslist] [-n namelist]\n"
254efd4c9b6SSteve Lawrence "             [-T u | d | i] [-R reports] [-q] [-p [-P lines]] [-S cols]\n"
255efd4c9b6SSteve Lawrence "             interval [duration [report]]\n"
256efd4c9b6SSteve Lawrence "\n");
257efd4c9b6SSteve Lawrence 	(void) fprintf(fd, gettext(
258efd4c9b6SSteve Lawrence "    Options:\n"
259efd4c9b6SSteve Lawrence "    %s    Report resources of specified types.\n"
260efd4c9b6SSteve Lawrence "	    Valid resource types are:\n"
261efd4c9b6SSteve Lawrence "	      \"%s\"\n"
262efd4c9b6SSteve Lawrence "	      \"%s\"\n"
263efd4c9b6SSteve Lawrence "	      \"%s\"\n"
264efd4c9b6SSteve Lawrence "	      \"%s\"\n"
265efd4c9b6SSteve Lawrence "	      \"%s\", \"%s\", \"%s\"\n"
266efd4c9b6SSteve Lawrence "	      \"%s\", \"%s\", \"%s\", \"%s\"\n"),
267efd4c9b6SSteve Lawrence 	    "-r",
272efd4c9b6SSteve Lawrence 	    ZONESTAT_MSG_IDS);
273efd4c9b6SSteve Lawrence 
274efd4c9b6SSteve Lawrence 	(void) fprintf(fd, gettext(
275efd4c9b6SSteve Lawrence "	    The following resource nicknames can also be specified:\n"
276efd4c9b6SSteve Lawrence "	      \"%s\"\n"
277efd4c9b6SSteve Lawrence "	      \"%s\"\n"
278efd4c9b6SSteve Lawrence "	      \"%s\"\n"
279efd4c9b6SSteve Lawrence "	      \"%s\"\n"
280efd4c9b6SSteve Lawrence "	      \"%s\"\n"
281efd4c9b6SSteve Lawrence "	      \"%s\"\n"),
284efd4c9b6SSteve Lawrence 	(void) fprintf(fd, gettext(
285efd4c9b6SSteve Lawrence "    %s    Report resources used by zones\n"
286efd4c9b6SSteve Lawrence "    %s    Report resources with specific names.\n"
287efd4c9b6SSteve Lawrence "	    Valid resource names are:\n"
288efd4c9b6SSteve Lawrence "	      \"%s\"\n"
289efd4c9b6SSteve Lawrence "	      \"%s\"\n"
290efd4c9b6SSteve Lawrence "	      Name of a pool processor set\n"
291*bbf21555SRichard Lowe "	      Id of a processor set created with psrset(8)\n"
292efd4c9b6SSteve Lawrence "	      Name of a zone using dedicated-cpu\n"),
293efd4c9b6SSteve Lawrence 	    "-z", "-n",
295881f4659SMarcel Telka 	(void) fprintf(fd, gettext(
296efd4c9b6SSteve Lawrence "    %s    Print timestamp. Valid timestamps are:\n"
297efd4c9b6SSteve Lawrence "	      \"%s\"\tDate as specifed by date(1) command\n"
298efd4c9b6SSteve Lawrence "	      \"%s\"\tUnix time as returned by time(2)\n"
299efd4c9b6SSteve Lawrence "	      \"%s\"\tISO 8601 timestamp \"%s\"\n"
300efd4c9b6SSteve Lawrence "    %s    Print reports at end or after each report interval.\n"
301efd4c9b6SSteve Lawrence "	    Valid reports are:\n"
302efd4c9b6SSteve Lawrence "	      \"%s\"\tUsage of each zone\n"
303efd4c9b6SSteve Lawrence "	      \"%s\"\tUsage of each zone while running\n"
304efd4c9b6SSteve Lawrence "	      \"%s\"\tMaximum usage of each zone\n"
305efd4c9b6SSteve Lawrence "    %s    Quiet.  Do not print intervals.  Only print reports.\n"
306efd4c9b6SSteve Lawrence "    %s    Machine parseable output.\n"),
307efd4c9b6SSteve Lawrence 	    "-T", "d", "u", "i", "YYYYMMDDThhmmssZ",
308efd4c9b6SSteve Lawrence 	    "-R", ZONESTAT_NAME_TOTAL, ZONESTAT_NAME_AVERAGE,
309efd4c9b6SSteve Lawrence 	    ZONESTAT_NAME_HIGH,
310efd4c9b6SSteve Lawrence 	    "-q", "-p");
311efd4c9b6SSteve Lawrence 
312881f4659SMarcel Telka 	(void) fprintf(fd, gettext(
313efd4c9b6SSteve Lawrence "    %s    Select desired lines in parseable output.\n"
314efd4c9b6SSteve Lawrence "	      \"%s\"\tLines describing each resource\n"
315efd4c9b6SSteve Lawrence "	      \"%s\"\tTotal usage of each resource\n"
316efd4c9b6SSteve Lawrence "	      \"%s\"\tSystem usage of each resource\n"
317efd4c9b6SSteve Lawrence "	      \"%s\"\tPer-zone usage of each resource\n"
318efd4c9b6SSteve Lawrence "	      \"%s\"\tHeader lines between intervals and reports\n"),
319efd4c9b6SSteve Lawrence 	    "-P", ZONESTAT_NAME_RESOURCE, ZONESTAT_NAME_TOTAL,
321efd4c9b6SSteve Lawrence 
322881f4659SMarcel Telka 	(void) fprintf(fd, gettext(
323efd4c9b6SSteve Lawrence "    %s    Sort output by the specified columns:\n"
324efd4c9b6SSteve Lawrence "	      \"%s\"\tby name alphanumerically\n"
325efd4c9b6SSteve Lawrence "	      \"%s\"\tby percent of resource used\n"
326efd4c9b6SSteve Lawrence "	      \"%s\"\tby configured cap\n"
327efd4c9b6SSteve Lawrence "	      \"%s\"\tby percent of cap used\n"
328efd4c9b6SSteve Lawrence "	      \"%s\"\tby shares configured\n"
329efd4c9b6SSteve Lawrence "	      \"%s\"\tby percent of share used\n"
330efd4c9b6SSteve Lawrence "	      \"%s\"\tSort summary by cpu\n"
331efd4c9b6SSteve Lawrence "	      \"%s\"\tSort summary by physical memory\n"
332efd4c9b6SSteve Lawrence "	      \"%s\"\tSort summary by virtual memory\n"),
336efd4c9b6SSteve Lawrence 	    ZONESTAT_NAME_VIRTUAL_MEMORY);
337efd4c9b6SSteve Lawrence 
338efd4c9b6SSteve Lawrence 	if (!explicit)
339efd4c9b6SSteve Lawrence 		(void) fputs("\n", fd);
340efd4c9b6SSteve Lawrence 	return (ZSTAT_USAGE);
341efd4c9b6SSteve Lawrence }
342efd4c9b6SSteve Lawrence 
343efd4c9b6SSteve Lawrence /* PRINTFLIKE1 */
344efd4c9b6SSteve Lawrence static int
zonestat_error(const char * fmt,...)345efd4c9b6SSteve Lawrence zonestat_error(const char *fmt, ...)
346efd4c9b6SSteve Lawrence {
347efd4c9b6SSteve Lawrence 	va_list alist;
348efd4c9b6SSteve Lawrence 
349efd4c9b6SSteve Lawrence 	va_start(alist, fmt);
350efd4c9b6SSteve Lawrence 
351efd4c9b6SSteve Lawrence 	(void) fprintf(stderr, "zonestat: Error: ");
352efd4c9b6SSteve Lawrence 	(void) vfprintf(stderr, fmt, alist);
353efd4c9b6SSteve Lawrence 	(void) fprintf(stderr, "\n");
354efd4c9b6SSteve Lawrence 	va_end(alist);
355efd4c9b6SSteve Lawrence 	return (ZSTAT_ERROR);
356efd4c9b6SSteve Lawrence }
357efd4c9b6SSteve Lawrence 
358efd4c9b6SSteve Lawrence static void
zonestat_determine_lines()359efd4c9b6SSteve Lawrence zonestat_determine_lines()
360efd4c9b6SSteve Lawrence {
361efd4c9b6SSteve Lawrence 	int i;
362efd4c9b6SSteve Lawrence 	boolean_t fail = B_FALSE;
363efd4c9b6SSteve Lawrence 
364efd4c9b6SSteve Lawrence 	if (arg_line_count == 0) {
365efd4c9b6SSteve Lawrence 		opt_line_resource = B_TRUE;
366efd4c9b6SSteve Lawrence 		opt_line_total = B_TRUE;
367efd4c9b6SSteve Lawrence 		opt_line_system = B_TRUE;
368efd4c9b6SSteve Lawrence 		opt_line_zones = B_TRUE;
369efd4c9b6SSteve Lawrence 		opt_line_header = B_TRUE;
370efd4c9b6SSteve Lawrence 	}
371efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_line_count; i++) {
372efd4c9b6SSteve Lawrence 		if (strcmp(arg_line_list[i], ZONESTAT_NAME_RESOURCE) == 0)
373efd4c9b6SSteve Lawrence 			opt_line_resource = B_TRUE;
374efd4c9b6SSteve Lawrence 		else if (strcmp(arg_line_list[i], ZONESTAT_NAME_TOTAL) == 0)
375efd4c9b6SSteve Lawrence 			opt_line_total = B_TRUE;
376efd4c9b6SSteve Lawrence 		else if (strcmp(arg_line_list[i], ZONESTAT_NAME_SYSTEM) == 0)
377efd4c9b6SSteve Lawrence 			opt_line_system = B_TRUE;
378efd4c9b6SSteve Lawrence 		else if (strcmp(arg_line_list[i], ZONESTAT_NAME_ZONES) == 0)
379efd4c9b6SSteve Lawrence 			opt_line_zones = B_TRUE;
380efd4c9b6SSteve Lawrence 		else if (strcmp(arg_line_list[i], ZONESTAT_NAME_HEADER) == 0)
381efd4c9b6SSteve Lawrence 			opt_line_header = B_TRUE;
382efd4c9b6SSteve Lawrence 		else {
383efd4c9b6SSteve Lawrence 			(void) zonestat_error(gettext("Unknown -O arg: %s"),
384efd4c9b6SSteve Lawrence 			    arg_line_list[i]);
385efd4c9b6SSteve Lawrence 			fail = B_TRUE;
386efd4c9b6SSteve Lawrence 		}
387efd4c9b6SSteve Lawrence 	}
388efd4c9b6SSteve Lawrence 	if (fail == B_TRUE)
389efd4c9b6SSteve Lawrence 		exit(zonestat_usage(B_FALSE));
390efd4c9b6SSteve Lawrence }
391efd4c9b6SSteve Lawrence 
392efd4c9b6SSteve Lawrence static void
zonestat_determine_reports()393efd4c9b6SSteve Lawrence zonestat_determine_reports()
394efd4c9b6SSteve Lawrence {
395efd4c9b6SSteve Lawrence 	int i;
396efd4c9b6SSteve Lawrence 	boolean_t fail = B_FALSE;
397efd4c9b6SSteve Lawrence 
398efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_report_count; i++) {
399efd4c9b6SSteve Lawrence 		if (strcmp(arg_reports[i], ZONESTAT_NAME_TOTAL) == 0)
400efd4c9b6SSteve Lawrence 			opt_report_total = B_TRUE;
401efd4c9b6SSteve Lawrence 		else if (strcmp(arg_reports[i], ZONESTAT_NAME_AVERAGE) == 0)
402efd4c9b6SSteve Lawrence 			opt_report_average = B_TRUE;
403efd4c9b6SSteve Lawrence 		else if (strcmp(arg_reports[i], ZONESTAT_NAME_HIGH) == 0)
404efd4c9b6SSteve Lawrence 			opt_report_high = B_TRUE;
405efd4c9b6SSteve Lawrence 		else {
406efd4c9b6SSteve Lawrence 			(void) zonestat_error(gettext("Unknown -R arg: %s"),
407efd4c9b6SSteve Lawrence 			    arg_reports[i]);
408efd4c9b6SSteve Lawrence 			fail = B_TRUE;
409efd4c9b6SSteve Lawrence 		}
410efd4c9b6SSteve Lawrence 	}
411efd4c9b6SSteve Lawrence 	if (fail == B_TRUE)
412efd4c9b6SSteve Lawrence 		exit(zonestat_usage(B_FALSE));
413efd4c9b6SSteve Lawrence }
414efd4c9b6SSteve Lawrence 
415efd4c9b6SSteve Lawrence /*
416efd4c9b6SSteve Lawrence  * Compares list of -S sort arguments to the list of known sorts.  Only
417efd4c9b6SSteve Lawrence  * one of cpu, physical memory, and virtual memory can be specified.
418efd4c9b6SSteve Lawrence  */
419efd4c9b6SSteve Lawrence static void
zonestat_determine_sort()420efd4c9b6SSteve Lawrence zonestat_determine_sort()
421efd4c9b6SSteve Lawrence {
422efd4c9b6SSteve Lawrence 	int i, count = 0;
423efd4c9b6SSteve Lawrence 	boolean_t fail = B_FALSE;
424efd4c9b6SSteve Lawrence 
425efd4c9b6SSteve Lawrence 	if (arg_sort_count == 0) {
426efd4c9b6SSteve Lawrence 		g_sort_summary = ZS_RESOURCE_CPU;
427efd4c9b6SSteve Lawrence 		g_sorts[0] = ZSTAT_SORT_USED;
428efd4c9b6SSteve Lawrence 		g_sorts[1] = ZSTAT_SORT_NAME;
429efd4c9b6SSteve Lawrence 		arg_sort_count = 2;
430efd4c9b6SSteve Lawrence 		return;
431efd4c9b6SSteve Lawrence 	}
432efd4c9b6SSteve Lawrence 
433efd4c9b6SSteve Lawrence 	if (arg_sort_count > ZSTAT_SORT_MAX)
434efd4c9b6SSteve Lawrence 		exit(zonestat_error(gettext(
435efd4c9b6SSteve Lawrence 		    "Too many -S sort columns specified")));
436efd4c9b6SSteve Lawrence 
437efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_sort_count; i++) {
438efd4c9b6SSteve Lawrence 		if (strcmp(arg_sort_list[i], ZONESTAT_NAME_NAME) == 0)
439efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_NAME;
440efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_USED) == 0)
441efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_USED;
442efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_CAP) == 0)
443efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_CAP;
444efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_PCAP) == 0)
445efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_PCAP;
446efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_SHR) == 0)
447efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_SHR;
448efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_PSHRU) == 0)
449efd4c9b6SSteve Lawrence 			g_sorts[count++] = ZSTAT_SORT_PSHRU;
450efd4c9b6SSteve Lawrence 		else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_CPU) == 0) {
451efd4c9b6SSteve Lawrence 			if (g_sort_summary != 0)
452efd4c9b6SSteve Lawrence 				fail = B_TRUE;
453efd4c9b6SSteve Lawrence 			g_sort_summary = ZS_RESOURCE_CPU;
454efd4c9b6SSteve Lawrence 		} else if (strcmp(arg_sort_list[i],
455efd4c9b6SSteve Lawrence 		    ZONESTAT_NAME_PHYSICAL_MEMORY) == 0) {
456efd4c9b6SSteve Lawrence 			if (g_sort_summary != 0)
457efd4c9b6SSteve Lawrence 				fail = B_TRUE;
458efd4c9b6SSteve Lawrence 			g_sort_summary = ZS_RESOURCE_RAM_RSS;
459efd4c9b6SSteve Lawrence 		} else if (strcmp(arg_sort_list[i],
460efd4c9b6SSteve Lawrence 		    ZONESTAT_NAME_VIRTUAL_MEMORY) == 0) {
461efd4c9b6SSteve Lawrence 			if (g_sort_summary != 0)
462efd4c9b6SSteve Lawrence 				fail = B_TRUE;
463efd4c9b6SSteve Lawrence 			g_sort_summary = ZS_RESOURCE_VM;
464efd4c9b6SSteve Lawrence 		} else {
465efd4c9b6SSteve Lawrence 			(void) zonestat_error(gettext("Unknown -S arg: %s"),
466efd4c9b6SSteve Lawrence 			    arg_sort_list[i]);
467efd4c9b6SSteve Lawrence 			fail = B_TRUE;
468efd4c9b6SSteve Lawrence 		}
469efd4c9b6SSteve Lawrence 	}
470efd4c9b6SSteve Lawrence 	if (g_sort_summary == 0)
471efd4c9b6SSteve Lawrence 		g_sort_summary = ZS_RESOURCE_CPU;
472efd4c9b6SSteve Lawrence 
473efd4c9b6SSteve Lawrence 	if (fail == B_TRUE) {
474efd4c9b6SSteve Lawrence 		(void) zonestat_error(gettext(
475efd4c9b6SSteve Lawrence 		    "-S: only one of \"%s\", \"%s\", or "
476efd4c9b6SSteve Lawrence 		    "\"%s\" permitted"), "-S", ZONESTAT_NAME_CPU,
477efd4c9b6SSteve Lawrence 		    ZONESTAT_NAME_PHYSICAL_MEMORY,
478efd4c9b6SSteve Lawrence 		    ZONESTAT_NAME_VIRTUAL_MEMORY);
479efd4c9b6SSteve Lawrence 		exit(zonestat_usage(B_FALSE));
480efd4c9b6SSteve Lawrence 	}
481efd4c9b6SSteve Lawrence }
482efd4c9b6SSteve Lawrence 
483efd4c9b6SSteve Lawrence typedef struct zonestat_resource_struct {
484efd4c9b6SSteve Lawrence 	char *zr_name;
485efd4c9b6SSteve Lawrence 	uint_t zr_flag;
486efd4c9b6SSteve Lawrence } zonestat_resource_t;
487efd4c9b6SSteve Lawrence 
488efd4c9b6SSteve Lawrence 
489efd4c9b6SSteve Lawrence /* Used to map resource name strings to resource flags */
490efd4c9b6SSteve Lawrence zonestat_resource_t g_resource_list[] = {
494efd4c9b6SSteve Lawrence 	ZONESTAT_MEMORY, ZSTAT_RES_MEMORY,
496efd4c9b6SSteve Lawrence 	ZONESTAT_PSETS, ZSTAT_RES_PSETS,
499efd4c9b6SSteve Lawrence 	ZONESTAT_LWPS, ZSTAT_RES_LWPS,
500efd4c9b6SSteve Lawrence 	ZONESTAT_LOFI, ZSTAT_RES_LOFI,
501efd4c9b6SSteve Lawrence 	ZONESTAT_LIMITS, ZSTAT_RES_LIMITS,
503efd4c9b6SSteve Lawrence 	ZONESTAT_SHM_IDS, ZSTAT_RES_SHM_IDS,
504efd4c9b6SSteve Lawrence 	ZONESTAT_SEM_IDS, ZSTAT_RES_SEM_IDS,
505efd4c9b6SSteve Lawrence 	ZONESTAT_MSG_IDS, ZSTAT_RES_MSG_IDS,
506efd4c9b6SSteve Lawrence 	ZONESTAT_SYSV, ZSTAT_RES_SYSV,
508efd4c9b6SSteve Lawrence 	ZONESTAT_ALL, ZSTAT_RES_ALL
509efd4c9b6SSteve Lawrence };
510efd4c9b6SSteve Lawrence 
511efd4c9b6SSteve Lawrence /*
512efd4c9b6SSteve Lawrence  * Compares list of resources passed to -r to the known list of
513efd4c9b6SSteve Lawrence  * resources.
514efd4c9b6SSteve Lawrence  */
515efd4c9b6SSteve Lawrence static void
zonestat_determine_resources()516efd4c9b6SSteve Lawrence zonestat_determine_resources()
517efd4c9b6SSteve Lawrence {
518efd4c9b6SSteve Lawrence 	int i, j, count;
519efd4c9b6SSteve Lawrence 	boolean_t found, fail = B_FALSE;
520efd4c9b6SSteve Lawrence 
521efd4c9b6SSteve Lawrence 	if (arg_restype_count == 0) {
522efd4c9b6SSteve Lawrence 		g_resources = ZSTAT_RES_SUMMARY;
523efd4c9b6SSteve Lawrence 		return;
524efd4c9b6SSteve Lawrence 	}
525efd4c9b6SSteve Lawrence 
526efd4c9b6SSteve Lawrence 	count = sizeof (g_resource_list) / sizeof (zonestat_resource_t);
527efd4c9b6SSteve Lawrence 
528efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_restype_count; i++) {
529efd4c9b6SSteve Lawrence 		found = B_FALSE;
530efd4c9b6SSteve Lawrence 		for (j = 0; j < count; j++) {
531efd4c9b6SSteve Lawrence 			if (strcmp(arg_restypes[i], g_resource_list[j].zr_name)
532efd4c9b6SSteve Lawrence 			    == 0) {
533efd4c9b6SSteve Lawrence 				g_resources |= g_resource_list[j].zr_flag;
534efd4c9b6SSteve Lawrence 				found = B_TRUE;
535efd4c9b6SSteve Lawrence 				break;
536efd4c9b6SSteve Lawrence 			}
537efd4c9b6SSteve Lawrence 		}
538efd4c9b6SSteve Lawrence 		if (found == B_FALSE) {
539efd4c9b6SSteve Lawrence 			(void) zonestat_error(gettext("Unknown resource: %s"),
540efd4c9b6SSteve Lawrence 			    arg_restypes[i]);
541efd4c9b6SSteve Lawrence 			fail = B_TRUE;
542efd4c9b6SSteve Lawrence 		}
543efd4c9b6SSteve Lawrence 	}
544efd4c9b6SSteve Lawrence 	if (fail == B_TRUE)
545efd4c9b6SSteve Lawrence 		exit(zonestat_usage(B_FALSE));
546efd4c9b6SSteve Lawrence }
547efd4c9b6SSteve Lawrence 
548efd4c9b6SSteve Lawrence /*
549efd4c9b6SSteve Lawrence  * Returns 1 if the name matches one of the specified zone names.  0
550efd4c9b6SSteve Lawrence  * otherwise.  Always matches if no zone names were specified.
551efd4c9b6SSteve Lawrence  */
552efd4c9b6SSteve Lawrence static int
zonestat_match_zonename(char * name)553efd4c9b6SSteve Lawrence zonestat_match_zonename(char *name)
554efd4c9b6SSteve Lawrence {
555efd4c9b6SSteve Lawrence 	int i;
556efd4c9b6SSteve Lawrence 
557efd4c9b6SSteve Lawrence 	if (arg_zonename_count == 0)
558efd4c9b6SSteve Lawrence 		return (1);
559efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_zonename_count; i++) {
560efd4c9b6SSteve Lawrence 		if (strcmp(name, arg_zonenames[i]) == 0)
561efd4c9b6SSteve Lawrence 			return (1);
562efd4c9b6SSteve Lawrence 	}
563efd4c9b6SSteve Lawrence 	return (0);
564efd4c9b6SSteve Lawrence }
565efd4c9b6SSteve Lawrence 
566efd4c9b6SSteve Lawrence /*
567efd4c9b6SSteve Lawrence  * compare name to base, ignoring prefix on name.
568efd4c9b6SSteve Lawrence  */
569efd4c9b6SSteve Lawrence static int
zonestat_match_with_prefix(char * prefix,char * name,char * base)570efd4c9b6SSteve Lawrence zonestat_match_with_prefix(char *prefix, char *name, char *base)
571efd4c9b6SSteve Lawrence {
572efd4c9b6SSteve Lawrence 	size_t prefix_len;
573efd4c9b6SSteve Lawrence 
574efd4c9b6SSteve Lawrence 	prefix_len = strlen(prefix);
575efd4c9b6SSteve Lawrence 	if (strncmp(name, prefix, prefix_len) == 0) {
576efd4c9b6SSteve Lawrence 		name += prefix_len;
577efd4c9b6SSteve Lawrence 		if (strcmp(name, base) == 0)
578efd4c9b6SSteve Lawrence 			return (1);
579efd4c9b6SSteve Lawrence 	}
580efd4c9b6SSteve Lawrence 	return (0);
581efd4c9b6SSteve Lawrence }
582efd4c9b6SSteve Lawrence /*
583efd4c9b6SSteve Lawrence  * Returns 1 if the resource matches one of the specified resource names.  0
584efd4c9b6SSteve Lawrence  * otherwise.  Always matches if no resource names were specified.
585efd4c9b6SSteve Lawrence  */
586efd4c9b6SSteve Lawrence static int
zonestat_match_resname(char * name)587efd4c9b6SSteve Lawrence zonestat_match_resname(char *name)
588efd4c9b6SSteve Lawrence {
589efd4c9b6SSteve Lawrence 	int i;
590efd4c9b6SSteve Lawrence 
591efd4c9b6SSteve Lawrence 	if (arg_resname_count == 0)
592efd4c9b6SSteve Lawrence 		return (1);
593efd4c9b6SSteve Lawrence 	for (i = 0; i < arg_resname_count; i++) {
594efd4c9b6SSteve Lawrence 
595efd4c9b6SSteve Lawrence 		if (strcmp(name, arg_resnames[i]) == 0)
596efd4c9b6SSteve Lawrence 			return (1);
597efd4c9b6SSteve Lawrence 
598efd4c9b6SSteve Lawrence 		if (zonestat_match_with_prefix("SUNWtmp_", name,
599efd4c9b6SSteve Lawrence 		    arg_resnames[i]))
600efd4c9b6SSteve Lawrence 			return (1);
601efd4c9b6SSteve Lawrence 
602efd4c9b6SSteve Lawrence 		if (zonestat_match_with_prefix("SUNWlegacy_pset_", name,
603efd4c9b6SSteve Lawrence 		    arg_resnames[i]))
604efd4c9b6SSteve Lawrence 			return (1);
605efd4c9b6SSteve Lawrence 	}
606efd4c9b6SSteve Lawrence 	return (0);
607efd4c9b6SSteve Lawrence }
608efd4c9b6SSteve Lawrence 
609efd4c9b6SSteve Lawrence /*
610efd4c9b6SSteve Lawrence  * Format unsigned uint64_t
611efd4c9b6SSteve Lawrence  *
612efd4c9b6SSteve Lawrence  * 9999  9999
613efd4c9b6SSteve Lawrence  * 99.9K 99999
614efd4c9b6SSteve Lawrence  * 9999K 9999999
615efd4c9b6SSteve Lawrence  * 99.9M 99999999
616efd4c9b6SSteve Lawrence  * 9999M 9999999999
617efd4c9b6SSteve Lawrence  * 99.9G 99999999999
618efd4c9b6SSteve Lawrence  * 9999G 9999999999999
619efd4c9b6SSteve Lawrence  * 99.9T 99999999999999
620efd4c9b6SSteve Lawrence  * 9999T 9999999999999999
621efd4c9b6SSteve Lawrence  * 99.9P 99999999999999999
622efd4c9b6SSteve Lawrence  * 9999P 9999999999999999999
623efd4c9b6SSteve Lawrence  * 99.9E UINT64_MAX
624efd4c9b6SSteve Lawrence  */
625efd4c9b6SSteve Lawrence static void
format_uint64(uint64_t val,char * str,size_t len)626efd4c9b6SSteve Lawrence format_uint64(uint64_t val, char *str, size_t len)
627efd4c9b6SSteve Lawrence {
628efd4c9b6SSteve Lawrence 	uint64_t high;
629efd4c9b6SSteve Lawrence 	uint64_t low;
630efd4c9b6SSteve Lawrence 
631efd4c9b6SSteve Lawrence 	if (val == UINT64_MAX) {
632efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "-");
633efd4c9b6SSteve Lawrence 		return;
634efd4c9b6SSteve Lawrence 	}
635efd4c9b6SSteve Lawrence 	if (val <= 9999) {
636efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu", val);
637efd4c9b6SSteve Lawrence 		return;
638efd4c9b6SSteve Lawrence 	}
639efd4c9b6SSteve Lawrence 	if (val <= 99999) {
640efd4c9b6SSteve Lawrence 		high = val / 1024;
641efd4c9b6SSteve Lawrence 		low = val * 10 / 1024 - (high * 10);
642efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu%1.1lluK", high, low);
643efd4c9b6SSteve Lawrence 		return;
644efd4c9b6SSteve Lawrence 	}
645efd4c9b6SSteve Lawrence 	val = val / 1024;
646efd4c9b6SSteve Lawrence 	if (val <= 9999 || opt_parseable) {
647efd4c9b6SSteve Lawrence 		high = val;
648efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluK", high);
649efd4c9b6SSteve Lawrence 		return;
650efd4c9b6SSteve Lawrence 	}
651efd4c9b6SSteve Lawrence 	if (val <= 99999) {
652efd4c9b6SSteve Lawrence 		high = val / 1024;
653efd4c9b6SSteve Lawrence 		low = val * 10 / 1024 - (high * 10);
654efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluM", high, low);
655efd4c9b6SSteve Lawrence 		return;
656efd4c9b6SSteve Lawrence 	}
657efd4c9b6SSteve Lawrence 	val = val / 1024;
658efd4c9b6SSteve Lawrence 	if (val <= 9999) {
659efd4c9b6SSteve Lawrence 		high = val;
660efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluM", high);
661efd4c9b6SSteve Lawrence 		return;
662efd4c9b6SSteve Lawrence 	}
663efd4c9b6SSteve Lawrence 	if (val <= 99999) {
664efd4c9b6SSteve Lawrence 		high = val / 1024;
665efd4c9b6SSteve Lawrence 		low = val * 10 / 1024 - (high * 10);
666efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluG", high, low);
667efd4c9b6SSteve Lawrence 		return;
668efd4c9b6SSteve Lawrence 	}
669efd4c9b6SSteve Lawrence 	val = val / 1024;
670efd4c9b6SSteve Lawrence 	if (val <= 9999) {
671efd4c9b6SSteve Lawrence 		high = val;
672efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluG", high);
673efd4c9b6SSteve Lawrence 		return;
674efd4c9b6SSteve Lawrence 	}
675efd4c9b6SSteve Lawrence 	if (val <= 99999) {
676efd4c9b6SSteve Lawrence 		high = val / 1024;
677efd4c9b6SSteve Lawrence 		low = val * 10 / 1024 - (high * 10);
678efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluT", high, low);
679efd4c9b6SSteve Lawrence 		return;
680efd4c9b6SSteve Lawrence 	}
681efd4c9b6SSteve Lawrence 	val = val / 1024;
682efd4c9b6SSteve Lawrence 	if (val <= 9999) {
683efd4c9b6SSteve Lawrence 		high = val;
684efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluT", high);
685efd4c9b6SSteve Lawrence 		return;
686efd4c9b6SSteve Lawrence 	}
687efd4c9b6SSteve Lawrence 	if (val <= 99999) {
688efd4c9b6SSteve Lawrence 		high = val / 1024;
689efd4c9b6SSteve Lawrence 		low = val * 10 / 1024 - (high * 10);
690efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluP", high, low);
691efd4c9b6SSteve Lawrence 		return;
692efd4c9b6SSteve Lawrence 	}
693efd4c9b6SSteve Lawrence 	val = val / 1024;
694efd4c9b6SSteve Lawrence 	if (val <= 9999) {
695efd4c9b6SSteve Lawrence 		high = val;
696efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluP", high);
697efd4c9b6SSteve Lawrence 		return;
698efd4c9b6SSteve Lawrence 	}
699efd4c9b6SSteve Lawrence 	high = val / 1024;
700efd4c9b6SSteve Lawrence 	low = val * 10 / 1024 - (high * 10);
701efd4c9b6SSteve Lawrence 	(void) snprintf(str, len, "%llu.%1.1lluE", high, low);
702efd4c9b6SSteve Lawrence }
703efd4c9b6SSteve Lawrence 
704efd4c9b6SSteve Lawrence 
705efd4c9b6SSteve Lawrence static void
format_pct(uint_t pct,char * str,size_t len)706efd4c9b6SSteve Lawrence format_pct(uint_t pct, char *str, size_t len)
707efd4c9b6SSteve Lawrence {
708efd4c9b6SSteve Lawrence 	uint_t high;
709efd4c9b6SSteve Lawrence 	uint_t low;
710efd4c9b6SSteve Lawrence 
711efd4c9b6SSteve Lawrence 	if (pct == ZS_PCT_NONE) {
712efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "-");
713efd4c9b6SSteve Lawrence 		return;
714efd4c9b6SSteve Lawrence 	}
715efd4c9b6SSteve Lawrence 	/*
716efd4c9b6SSteve Lawrence 	 * pct's are printed as one of:
717efd4c9b6SSteve Lawrence 	 *	#.##%
718efd4c9b6SSteve Lawrence 	 *	##.#%
719efd4c9b6SSteve Lawrence 	 *	 ###%
720efd4c9b6SSteve Lawrence 	 *	####%
721efd4c9b6SSteve Lawrence 	 *
722efd4c9b6SSteve Lawrence 	 * The value is fixed decimal.  10000 equals 100.00 percent.
723efd4c9b6SSteve Lawrence 	 * Percents can exceed 100.00 percent.  Percents greater than
724efd4c9b6SSteve Lawrence 	 * 9999% will exceed the 5 column width.
725efd4c9b6SSteve Lawrence 	 */
726efd4c9b6SSteve Lawrence 	if (pct <= 999 || opt_parseable) {
727efd4c9b6SSteve Lawrence 		high = pct / 100;
728efd4c9b6SSteve Lawrence 		low = pct - (high * 100);
729efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%u.%2.2u%%", high, low);
730efd4c9b6SSteve Lawrence 	} else if (pct <= 9999) {
731efd4c9b6SSteve Lawrence 		pct = pct / 10;
732efd4c9b6SSteve Lawrence 		high = pct / 10;
733efd4c9b6SSteve Lawrence 		low = pct - (high * 10);
734efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%u.%1.1u%%", high, low);
735efd4c9b6SSteve Lawrence 	} else {
736efd4c9b6SSteve Lawrence 		pct = pct / 100;
737efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%u%%", pct);
738efd4c9b6SSteve Lawrence 	}
739efd4c9b6SSteve Lawrence }
740efd4c9b6SSteve Lawrence /*
741efd4c9b6SSteve Lawrence  * Cpu cap is 100 times the number of cpus allocated.  It is formatted as a
742efd4c9b6SSteve Lawrence  * decimal.  Example, a cpu-cap of 50 is 0.50 cpus.
743efd4c9b6SSteve Lawrence  *
744efd4c9b6SSteve Lawrence  * The cpu cap value can go up to UINT_MAX, so handle all cases even though
745efd4c9b6SSteve Lawrence  * the higher ones are nonsense.
746efd4c9b6SSteve Lawrence  *
747efd4c9b6SSteve Lawrence  * Format  Max cpu-cap value for format.
748efd4c9b6SSteve Lawrence  * 42.9M   4294967296
749efd4c9b6SSteve Lawrence  * 9999K   999999999
750efd4c9b6SSteve Lawrence  * 99.9K   9999999
751efd4c9b6SSteve Lawrence  *  9999   999999
752efd4c9b6SSteve Lawrence  * 999.9   99999
753efd4c9b6SSteve Lawrence  *  9.99   999
754efd4c9b6SSteve Lawrence  */
755efd4c9b6SSteve Lawrence void
format_cpu(uint64_t cpu,char * str,size_t len)756efd4c9b6SSteve Lawrence format_cpu(uint64_t cpu, char *str, size_t len)
757efd4c9b6SSteve Lawrence {
758efd4c9b6SSteve Lawrence 
759efd4c9b6SSteve Lawrence 	uint64_t high;
760efd4c9b6SSteve Lawrence 	uint64_t low;
761efd4c9b6SSteve Lawrence 
762efd4c9b6SSteve Lawrence 	/* #.## cpus */
763efd4c9b6SSteve Lawrence 	if (cpu <= 999 || opt_parseable) {
764efd4c9b6SSteve Lawrence 		high = cpu / 100;
765efd4c9b6SSteve Lawrence 		low = cpu - (high * 100);
766efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%2.2llu", high, low);
767efd4c9b6SSteve Lawrence 		return;
768efd4c9b6SSteve Lawrence 	}
769efd4c9b6SSteve Lawrence 	/* ##.# cpus */
770efd4c9b6SSteve Lawrence 	if (cpu <= 99999) {
771efd4c9b6SSteve Lawrence 		high = cpu / 100;
772efd4c9b6SSteve Lawrence 		low = cpu - (high * 100);
773efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1llu", high, low);
774efd4c9b6SSteve Lawrence 		return;
775efd4c9b6SSteve Lawrence 	}
776efd4c9b6SSteve Lawrence 	/* #### cpus */
777efd4c9b6SSteve Lawrence 	if (cpu <= 999999) {
778efd4c9b6SSteve Lawrence 		cpu = cpu / 100;
779efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu", cpu);
780efd4c9b6SSteve Lawrence 		return;
781efd4c9b6SSteve Lawrence 	}
782efd4c9b6SSteve Lawrence 	/* ##.#K cpus */
783efd4c9b6SSteve Lawrence 	cpu = cpu / 1000;
784efd4c9b6SSteve Lawrence 	if (cpu <= 99999) {
785efd4c9b6SSteve Lawrence 		high = cpu / 100;
786efd4c9b6SSteve Lawrence 		low = cpu - (high * 100);
787efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluK", high, low);
788efd4c9b6SSteve Lawrence 		return;
789efd4c9b6SSteve Lawrence 	}
790efd4c9b6SSteve Lawrence 	/* ####K cpus */
791efd4c9b6SSteve Lawrence 	if (cpu <= 999999) {
792efd4c9b6SSteve Lawrence 		cpu = cpu / 100;
793efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%lluK", cpu);
794efd4c9b6SSteve Lawrence 		return;
795efd4c9b6SSteve Lawrence 	}
796efd4c9b6SSteve Lawrence 	/* ##.#M cpus */
797efd4c9b6SSteve Lawrence 	cpu = cpu / 1000;
798efd4c9b6SSteve Lawrence 	if (cpu <= UINT_MAX) {
799efd4c9b6SSteve Lawrence 		high = cpu / 100;
800efd4c9b6SSteve Lawrence 		low = cpu - (high * 100);
801efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu.%1.1lluM", high, low);
802efd4c9b6SSteve Lawrence 		return;
803efd4c9b6SSteve Lawrence 	}
804efd4c9b6SSteve Lawrence 	(void) snprintf(str, len, "error", high, low);
805efd4c9b6SSteve Lawrence }
806efd4c9b6SSteve Lawrence 
807efd4c9b6SSteve Lawrence /*
808efd4c9b6SSteve Lawrence  * Format a timetruct as:
809efd4c9b6SSteve Lawrence  * HH:MM:SS.SS
810efd4c9b6SSteve Lawrence  *
811efd4c9b6SSteve Lawrence  * Human readable format omits the fractional seconds.
812efd4c9b6SSteve Lawrence  */
813efd4c9b6SSteve Lawrence static void
format_ts(timestruc_t * ts,char * str,size_t len,boolean_t human_readable)814efd4c9b6SSteve Lawrence format_ts(timestruc_t *ts, char *str, size_t len, boolean_t human_readable)
815efd4c9b6SSteve Lawrence {
816efd4c9b6SSteve Lawrence 	uint64_t secs, mins, hours, pct;
817efd4c9b6SSteve Lawrence 
818efd4c9b6SSteve Lawrence 	hours = 0;
819efd4c9b6SSteve Lawrence 	mins = 0;
820efd4c9b6SSteve Lawrence 
821efd4c9b6SSteve Lawrence 	secs = ts->tv_sec;
822efd4c9b6SSteve Lawrence 	pct = ts->tv_nsec / 1000 / 1000 / 10;
823efd4c9b6SSteve Lawrence 	while (pct >= 100) {
824efd4c9b6SSteve Lawrence 		pct -= 100;
825efd4c9b6SSteve Lawrence 		secs++;
826efd4c9b6SSteve Lawrence 	}
827efd4c9b6SSteve Lawrence 	if (secs >= 60) {
828efd4c9b6SSteve Lawrence 		mins = secs / 60;
829efd4c9b6SSteve Lawrence 		secs = secs % 60;
830efd4c9b6SSteve Lawrence 	}
831efd4c9b6SSteve Lawrence 	if (mins >= 60) {
832efd4c9b6SSteve Lawrence 		hours = mins / 60;
833efd4c9b6SSteve Lawrence 		mins = mins % 60;
834efd4c9b6SSteve Lawrence 	}
835efd4c9b6SSteve Lawrence 	if (human_readable)
836efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu:%2.2llu:%2.2llu", hours,
837efd4c9b6SSteve Lawrence 		    mins, secs);
838efd4c9b6SSteve Lawrence 	else
839efd4c9b6SSteve Lawrence 		(void) snprintf(str, len, "%llu-%2.2llu-%2.2llu.%2.2llu", hours,
840efd4c9b6SSteve Lawrence 		    mins, secs, pct);
841efd4c9b6SSteve Lawrence }
842efd4c9b6SSteve Lawrence 
843efd4c9b6SSteve Lawrence char *g_report_formats[] = {
844efd4c9b6SSteve Lawrence 	ZSTAT_REPORT_TEXT_INTERVAL,
845efd4c9b6SSteve Lawrence 	ZSTAT_REPORT_TEXT_TOTAL,
846efd4c9b6SSteve Lawrence 	ZSTAT_REPORT_TEXT_AVERAGE,
847efd4c9b6SSteve Lawrence 	ZSTAT_REPORT_TEXT_HIGH,
848efd4c9b6SSteve Lawrence 	ZSTAT_REPORT_TEXT_END
849efd4c9b6SSteve Lawrence };
850efd4c9b6SSteve Lawrence 
851efd4c9b6SSteve Lawrence /* Get the label for the current report type */
852efd4c9b6SSteve Lawrence static char *
zonestat_get_plabel(int format)853efd4c9b6SSteve Lawrence zonestat_get_plabel(int format)
854efd4c9b6SSteve Lawrence {
855efd4c9b6SSteve Lawrence 	if (format >= sizeof (g_report_formats) / sizeof (char *))
856efd4c9b6SSteve Lawrence 		exit(zonestat_error(gettext(
857efd4c9b6SSteve Lawrence 		    "Internal error, invalid report format")));
858efd4c9b6SSteve Lawrence 
859efd4c9b6SSteve Lawrence 	return (g_report_formats[format]);
860efd4c9b6SSteve Lawrence }
861efd4c9b6SSteve Lawrence 
862efd4c9b6SSteve Lawrence #define	ZSTAT_CPULINE "----------CPU----------"
863efd4c9b6SSteve Lawrence #define	ZSTAT_MEMLINE "----PHYSICAL-----"
864efd4c9b6SSteve Lawrence #define	ZSTAT_VMLINE  "-----VIRTUAL-----"
865efd4c9b6SSteve Lawrence 
866efd4c9b6SSteve Lawrence static void
zonestat_print_summary_header(size_t namewidth,int report_fmt,uint64_t cpu,uint64_t online,uint64_t mem,uint64_t vm)867efd4c9b6SSteve Lawrence zonestat_print_summary_header(size_t namewidth, int report_fmt, uint64_t cpu,
868efd4c9b6SSteve Lawrence     uint64_t online, uint64_t mem, uint64_t vm)
869efd4c9b6SSteve Lawrence {
870efd4c9b6SSteve Lawrence 	char str_cpu[ZS_UINT64_STRLEN];
871efd4c9b6SSteve Lawrence 	char str_online[ZS_UINT64_STRLEN];
872efd4c9b6SSteve Lawrence 	char str_mem[ZS_UINT64_STRLEN];
873efd4c9b6SSteve Lawrence 	char str_vm[ZS_UINT64_STRLEN];
874efd4c9b6SSteve Lawrence 	char name_format[ZS_NAME_STRLEN];
875efd4c9b6SSteve Lawrence 	char tot_cpu[sizeof (ZSTAT_CPULINE)];
876efd4c9b6SSteve Lawrence 	char tot_mem[sizeof (ZSTAT_MEMLINE)];
877efd4c9b6SSteve Lawrence 	char tot_vm[sizeof (ZSTAT_VMLINE)];
878efd4c9b6SSteve Lawrence 
879efd4c9b6SSteve Lawrence 	char *label;
880efd4c9b6SSteve Lawrence 
881efd4c9b6SSteve Lawrence 	format_uint64(cpu, str_cpu, sizeof (str_cpu));
882efd4c9b6SSteve Lawrence 	format_uint64(online, str_online, sizeof (str_online));
883efd4c9b6SSteve Lawrence 	format_uint64(mem, str_mem, sizeof (str_mem));
884efd4c9b6SSteve Lawrence 	format_uint64(vm, str_vm, sizeof (str_vm));
885efd4c9b6SSteve Lawrence 
886efd4c9b6SSteve Lawrence 	if (opt_parseable) {
887efd4c9b6SSteve Lawrence 		label = zonestat_get_plabel(report_fmt);
888efd4c9b6SSteve Lawrence 		(void) printf("%s:%s:[%s]:%s:%s:%s:%s\n", label,
889efd4c9b6SSteve Lawrence 		    ZONESTAT_SUMMARY, ZONESTAT_NAME_RESOURCE, str_cpu,
890efd4c9b6SSteve Lawrence 		    str_online, str_mem, str_vm);
891efd4c9b6SSteve Lawrence 		return;
892efd4c9b6SSteve Lawrence 	}
893efd4c9b6SSteve Lawrence 
894efd4c9b6SSteve Lawrence 	(void) snprintf(tot_cpu, sizeof (tot_cpu), "Cpus/Online: %s/%s",
895efd4c9b6SSteve Lawrence 	    str_cpu, str_online);
896efd4c9b6SSteve Lawrence 
897efd4c9b6SSteve Lawrence 	(void) snprintf(tot_mem, sizeof (tot_mem), "Physical: %s", str_mem);
898efd4c9b6SSteve Lawrence 
899efd4c9b6SSteve Lawrence 	(void) snprintf(tot_vm, sizeof (tot_vm), "Virtual: %s", str_vm);
900efd4c9b6SSteve Lawrence 
901efd4c9b6SSteve Lawrence 	/* Make first column as wide as longest zonename */
902efd4c9b6SSteve Lawrence 	(void) snprintf(name_format, sizeof (name_format), "%%-%ds ",
903efd4c9b6SSteve Lawrence 	    namewidth);
904efd4c9b6SSteve Lawrence 	/* LINTED */
905efd4c9b6SSteve Lawrence 	(void) printf(name_format, "SUMMARY");
906efd4c9b6SSteve Lawrence 	(void) printf(ZSTAT_SUM_HDR_FORMAT, tot_cpu, tot_mem,
907efd4c9b6SSteve Lawrence 	    tot_vm);
908efd4c9b6SSteve Lawrence 
909efd4c9b6SSteve Lawrence 	/* LINTED */
910efd4c9b6SSteve Lawrence 	(void) printf(name_format, "");
911efd4c9b6SSteve Lawrence 	(void) printf(ZSTAT_SUM_HDR_FORMAT, ZSTAT_CPULINE,
912efd4c9b6SSteve Lawrence 	    ZSTAT_MEMLINE, ZSTAT_VMLINE);
913efd4c9b6SSteve Lawrence 
914efd4c9b6SSteve Lawrence 	(void) snprintf(name_format, sizeof (name_format), "%%%ds ",
915efd4c9b6SSteve Lawrence 	    namewidth);
916efd4c9b6SSteve Lawrence 	/* LINTED */
917efd4c9b6SSteve Lawrence 	(void) printf(name_format, "ZONE");
918efd4c9b6SSteve Lawrence 
919efd4c9b6SSteve Lawrence 	(void) printf(ZSTAT_SUM_ZONE_FORMAT, "USED", "%PART", "%CAP",
920efd4c9b6SSteve Lawrence 	    "%SHRU", "USED", "PCT", "%CAP", "USED", "PCT", "%CAP");
921efd4c9b6SSteve Lawrence }
922efd4c9b6SSteve Lawrence 
923efd4c9b6SSteve Lawrence static void
zonestat_print_resource__header(size_t namelen,char * restype,char * size)924efd4c9b6SSteve Lawrence zonestat_print_resource__header(size_t namelen, char *restype, char *size)
925efd4c9b6SSteve Lawrence {
926efd4c9b6SSteve Lawrence 	char name_format[ZS_NAME_STRLEN];
927efd4c9b6SSteve Lawrence 
928efd4c9b6SSteve Lawrence 	if (opt_parseable)
929efd4c9b6SSteve Lawrence 		return;
930efd4c9b6SSteve Lawrence 
931efd4c9b6SSteve Lawrence 	(void) snprintf(name_format, sizeof (name_format), "%%-%ds ", namelen);
932efd4c9b6SSteve Lawrence 	/* LINTED */
933efd4c9b6SSteve Lawrence 	(void) printf(name_format, restype);
934efd4c9b6SSteve Lawrence 	(void) printf(ZSTAT_RESOURCE_FORMAT, size);
935efd4c9b6SSteve Lawrence }
936efd4c9b6SSteve Lawrence 
937efd4c9b6SSteve Lawrence static void
zonestat_print_resource_zone_header(size_t namelen)938