xref: /freebsd/usr.bin/procstat/procstat_files.c (revision 7493f24ee6846df33931904c87493b08400df5bd)
13d91be41SRobert Watson /*-
2d57486e2SRobert Watson  * Copyright (c) 2007-2011 Robert N. M. Watson
33d91be41SRobert Watson  * All rights reserved.
43d91be41SRobert Watson  *
53d91be41SRobert Watson  * Redistribution and use in source and binary forms, with or without
63d91be41SRobert Watson  * modification, are permitted provided that the following conditions
73d91be41SRobert Watson  * are met:
83d91be41SRobert Watson  * 1. Redistributions of source code must retain the above copyright
93d91be41SRobert Watson  *    notice, this list of conditions and the following disclaimer.
103d91be41SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
113d91be41SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
123d91be41SRobert Watson  *    documentation and/or other materials provided with the distribution.
133d91be41SRobert Watson  *
143d91be41SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
153d91be41SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
163d91be41SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
173d91be41SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
183d91be41SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193d91be41SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
203d91be41SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
213d91be41SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
223d91be41SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
233d91be41SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
243d91be41SRobert Watson  * SUCH DAMAGE.
253d91be41SRobert Watson  *
263d91be41SRobert Watson  * $FreeBSD$
273d91be41SRobert Watson  */
283d91be41SRobert Watson 
29e1f323f3SRobert Watson #include <sys/param.h>
30d57486e2SRobert Watson #include <sys/capability.h>
313d91be41SRobert Watson #include <sys/socket.h>
323d91be41SRobert Watson #include <sys/sysctl.h>
333d91be41SRobert Watson #include <sys/un.h>
343d91be41SRobert Watson #include <sys/user.h>
353d91be41SRobert Watson 
363d91be41SRobert Watson #include <netinet/in.h>
373d91be41SRobert Watson 
383d91be41SRobert Watson #include <arpa/inet.h>
393d91be41SRobert Watson 
40821df508SXin LI #include <err.h>
410daf62d9SStanislav Sedov #include <libprocstat.h>
423d91be41SRobert Watson #include <inttypes.h>
433d91be41SRobert Watson #include <stdio.h>
443d91be41SRobert Watson #include <stdlib.h>
453d91be41SRobert Watson #include <string.h>
463d91be41SRobert Watson 
473d91be41SRobert Watson #include "procstat.h"
483d91be41SRobert Watson 
493d91be41SRobert Watson static const char *
503d91be41SRobert Watson protocol_to_string(int domain, int type, int protocol)
513d91be41SRobert Watson {
523d91be41SRobert Watson 
533d91be41SRobert Watson 	switch (domain) {
543d91be41SRobert Watson 	case AF_INET:
553d91be41SRobert Watson 	case AF_INET6:
563d91be41SRobert Watson 		switch (protocol) {
573d91be41SRobert Watson 		case IPPROTO_TCP:
583d91be41SRobert Watson 			return ("TCP");
593d91be41SRobert Watson 		case IPPROTO_UDP:
603d91be41SRobert Watson 			return ("UDP");
613d91be41SRobert Watson 		case IPPROTO_ICMP:
625a246d29SRobert Watson 			return ("ICM");
633d91be41SRobert Watson 		case IPPROTO_RAW:
643d91be41SRobert Watson 			return ("RAW");
653d91be41SRobert Watson 		case IPPROTO_SCTP:
665a246d29SRobert Watson 			return ("SCT");
675a246d29SRobert Watson 		case IPPROTO_DIVERT:
685a246d29SRobert Watson 			return ("IPD");
693d91be41SRobert Watson 		default:
705a246d29SRobert Watson 			return ("IP?");
713d91be41SRobert Watson 		}
723d91be41SRobert Watson 
733d91be41SRobert Watson 	case AF_LOCAL:
743d91be41SRobert Watson 		switch (type) {
753d91be41SRobert Watson 		case SOCK_STREAM:
765a246d29SRobert Watson 			return ("UDS");
773d91be41SRobert Watson 		case SOCK_DGRAM:
785a246d29SRobert Watson 			return ("UDD");
793d91be41SRobert Watson 		default:
805a246d29SRobert Watson 			return ("UD?");
813d91be41SRobert Watson 		}
823d91be41SRobert Watson 	default:
835a246d29SRobert Watson 		return ("?");
843d91be41SRobert Watson 	}
853d91be41SRobert Watson }
863d91be41SRobert Watson 
873d91be41SRobert Watson static void
883d91be41SRobert Watson addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
893d91be41SRobert Watson {
903d91be41SRobert Watson 	char buffer2[INET6_ADDRSTRLEN];
913d91be41SRobert Watson 	struct sockaddr_in6 *sin6;
923d91be41SRobert Watson 	struct sockaddr_in *sin;
933d91be41SRobert Watson 	struct sockaddr_un *sun;
943d91be41SRobert Watson 
953d91be41SRobert Watson 	switch (ss->ss_family) {
963d91be41SRobert Watson 	case AF_LOCAL:
973d91be41SRobert Watson 		sun = (struct sockaddr_un *)ss;
983d91be41SRobert Watson 		if (strlen(sun->sun_path) == 0)
993d91be41SRobert Watson 			strlcpy(buffer, "-", buflen);
1003d91be41SRobert Watson 		else
1013d91be41SRobert Watson 			strlcpy(buffer, sun->sun_path, buflen);
1023d91be41SRobert Watson 		break;
1033d91be41SRobert Watson 
1043d91be41SRobert Watson 	case AF_INET:
1053d91be41SRobert Watson 		sin = (struct sockaddr_in *)ss;
1063d91be41SRobert Watson 		snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr),
1073d91be41SRobert Watson 		    ntohs(sin->sin_port));
1083d91be41SRobert Watson 		break;
1093d91be41SRobert Watson 
1103d91be41SRobert Watson 	case AF_INET6:
1113d91be41SRobert Watson 		sin6 = (struct sockaddr_in6 *)ss;
1123d91be41SRobert Watson 		if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
1133d91be41SRobert Watson 		    sizeof(buffer2)) != NULL)
1143d91be41SRobert Watson 			snprintf(buffer, buflen, "%s.%d", buffer2,
1153d91be41SRobert Watson 			    ntohs(sin6->sin6_port));
1163d91be41SRobert Watson 		else
1173d91be41SRobert Watson 			strlcpy(buffer, "-", sizeof(buffer));
1183d91be41SRobert Watson 		break;
1193d91be41SRobert Watson 
1203d91be41SRobert Watson 	default:
1213d91be41SRobert Watson 		strlcpy(buffer, "", buflen);
1223d91be41SRobert Watson 		break;
1233d91be41SRobert Watson 	}
1243d91be41SRobert Watson }
1253d91be41SRobert Watson 
1263d91be41SRobert Watson static void
1273d91be41SRobert Watson print_address(struct sockaddr_storage *ss)
1283d91be41SRobert Watson {
1293d91be41SRobert Watson 	char addr[PATH_MAX];
1303d91be41SRobert Watson 
1313d91be41SRobert Watson 	addr_to_string(ss, addr, sizeof(addr));
1325a246d29SRobert Watson 	printf("%s", addr);
1333d91be41SRobert Watson }
1343d91be41SRobert Watson 
135d57486e2SRobert Watson static struct cap_desc {
136d57486e2SRobert Watson 	cap_rights_t	 cd_right;
137d57486e2SRobert Watson 	const char	*cd_desc;
138d57486e2SRobert Watson } cap_desc[] = {
139d57486e2SRobert Watson 	/* General file I/O. */
140d57486e2SRobert Watson 	{ CAP_READ,		"rd" },
141d57486e2SRobert Watson 	{ CAP_WRITE,		"wr" },
1422609222aSPawel Jakub Dawidek 	{ CAP_SEEK,		"se" },
143d57486e2SRobert Watson 	{ CAP_MMAP,		"mm" },
1442609222aSPawel Jakub Dawidek 	{ CAP_CREATE,		"cr" },
145d57486e2SRobert Watson 	{ CAP_FEXECVE,		"fe" },
146d57486e2SRobert Watson 	{ CAP_FSYNC,		"fy" },
147d57486e2SRobert Watson 	{ CAP_FTRUNCATE,	"ft" },
148d57486e2SRobert Watson 
149d57486e2SRobert Watson 	/* VFS methods. */
150d57486e2SRobert Watson 	{ CAP_FCHDIR,		"cd" },
1512609222aSPawel Jakub Dawidek 	{ CAP_FCHFLAGS,		"cf" },
152d57486e2SRobert Watson 	{ CAP_FCHMOD,		"cm" },
153d57486e2SRobert Watson 	{ CAP_FCHOWN,		"cn" },
154d57486e2SRobert Watson 	{ CAP_FCNTL,		"fc" },
155d57486e2SRobert Watson 	{ CAP_FLOCK,		"fl" },
1562609222aSPawel Jakub Dawidek 	{ CAP_FPATHCONF,	"fp" },
157d57486e2SRobert Watson 	{ CAP_FSCK,		"fk" },
158d57486e2SRobert Watson 	{ CAP_FSTAT,		"fs" },
159d57486e2SRobert Watson 	{ CAP_FSTATFS,		"sf" },
160d57486e2SRobert Watson 	{ CAP_FUTIMES,		"fu" },
1612609222aSPawel Jakub Dawidek 	{ CAP_LINKAT,		"li" },
1622609222aSPawel Jakub Dawidek 	{ CAP_MKDIRAT,		"md" },
1632609222aSPawel Jakub Dawidek 	{ CAP_MKFIFOAT,		"mf" },
1642609222aSPawel Jakub Dawidek 	{ CAP_MKNODAT,		"mn" },
1652609222aSPawel Jakub Dawidek 	{ CAP_RENAMEAT,		"rn" },
1662609222aSPawel Jakub Dawidek 	{ CAP_SYMLINKAT,	"sl" },
1672609222aSPawel Jakub Dawidek 	{ CAP_UNLINKAT,		"un" },
168d57486e2SRobert Watson 
1692609222aSPawel Jakub Dawidek 	/* Lookups - used to constrain *at() calls. */
170d57486e2SRobert Watson 	{ CAP_LOOKUP,		"lo" },
171d57486e2SRobert Watson 
172d57486e2SRobert Watson 	/* Extended attributes. */
173d57486e2SRobert Watson 	{ CAP_EXTATTR_GET,	"eg" },
174d57486e2SRobert Watson 	{ CAP_EXTATTR_SET,	"es" },
175d57486e2SRobert Watson 	{ CAP_EXTATTR_DELETE,	"ed" },
176d57486e2SRobert Watson 	{ CAP_EXTATTR_LIST,	"el" },
177d57486e2SRobert Watson 
178d57486e2SRobert Watson 	/* Access Control Lists. */
179d57486e2SRobert Watson 	{ CAP_ACL_GET,		"ag" },
180d57486e2SRobert Watson 	{ CAP_ACL_SET,		"as" },
181d57486e2SRobert Watson 	{ CAP_ACL_DELETE,	"ad" },
182d57486e2SRobert Watson 	{ CAP_ACL_CHECK,	"ac" },
183d57486e2SRobert Watson 
184d57486e2SRobert Watson 	/* Socket operations. */
185d57486e2SRobert Watson 	{ CAP_ACCEPT,		"at" },
186d57486e2SRobert Watson 	{ CAP_BIND,		"bd" },
187d57486e2SRobert Watson 	{ CAP_CONNECT,		"co" },
188d57486e2SRobert Watson 	{ CAP_GETPEERNAME,	"pn" },
189d57486e2SRobert Watson 	{ CAP_GETSOCKNAME,	"sn" },
190d57486e2SRobert Watson 	{ CAP_GETSOCKOPT,	"gs" },
191d57486e2SRobert Watson 	{ CAP_LISTEN,		"ln" },
192d57486e2SRobert Watson 	{ CAP_PEELOFF,		"pf" },
193d57486e2SRobert Watson 	{ CAP_SETSOCKOPT,	"ss" },
194d57486e2SRobert Watson 	{ CAP_SHUTDOWN,		"sh" },
195d57486e2SRobert Watson 
196d57486e2SRobert Watson 	/* Mandatory Access Control. */
197d57486e2SRobert Watson 	{ CAP_MAC_GET,		"mg" },
198d57486e2SRobert Watson 	{ CAP_MAC_SET,		"ms" },
199d57486e2SRobert Watson 
200d57486e2SRobert Watson 	/* Methods on semaphores. */
201d57486e2SRobert Watson 	{ CAP_SEM_GETVALUE,	"sg" },
202d57486e2SRobert Watson 	{ CAP_SEM_POST,		"sp" },
203d57486e2SRobert Watson 	{ CAP_SEM_WAIT,		"sw" },
204d57486e2SRobert Watson 
205d57486e2SRobert Watson 	/* Event monitoring and posting. */
206d57486e2SRobert Watson 	{ CAP_POLL_EVENT,	"po" },
207d57486e2SRobert Watson 	{ CAP_POST_EVENT,	"ev" },
208d57486e2SRobert Watson 
209d57486e2SRobert Watson 	/* Strange and powerful rights that should not be given lightly. */
210d57486e2SRobert Watson 	{ CAP_IOCTL,		"io" },
211d57486e2SRobert Watson 	{ CAP_TTYHOOK,		"ty" },
212d57486e2SRobert Watson 
2136a9f247cSPawel Jakub Dawidek 	/* Process management via process descriptors. */
214d57486e2SRobert Watson 	{ CAP_PDGETPID,		"pg" },
2156a9f247cSPawel Jakub Dawidek 	{ CAP_PDWAIT,		"pw" },
216d57486e2SRobert Watson 	{ CAP_PDKILL,		"pk" },
2172609222aSPawel Jakub Dawidek 
218*7493f24eSPawel Jakub Dawidek 	/*
219*7493f24eSPawel Jakub Dawidek 	 * Rights that allow to use bindat(2) and connectat(2) syscalls on a
220*7493f24eSPawel Jakub Dawidek 	 * directory descriptor.
221*7493f24eSPawel Jakub Dawidek 	 */
222*7493f24eSPawel Jakub Dawidek 	{ CAP_BINDAT,		"ba" },
223*7493f24eSPawel Jakub Dawidek 	{ CAP_CONNECTAT,	"ca" },
224*7493f24eSPawel Jakub Dawidek 
2252609222aSPawel Jakub Dawidek 	/* Aliases and defines that combine multiple rights. */
2262609222aSPawel Jakub Dawidek 	{ CAP_PREAD,		"prd" },
2272609222aSPawel Jakub Dawidek 	{ CAP_PWRITE,		"pwr" },
2282609222aSPawel Jakub Dawidek 
2292609222aSPawel Jakub Dawidek 	{ CAP_MMAP_R,		"mmr" },
2302609222aSPawel Jakub Dawidek 	{ CAP_MMAP_W,		"mmw" },
2312609222aSPawel Jakub Dawidek 	{ CAP_MMAP_X,		"mmx" },
2322609222aSPawel Jakub Dawidek 	{ CAP_MMAP_RW,		"mrw" },
2332609222aSPawel Jakub Dawidek 	{ CAP_MMAP_RX,		"mrx" },
2342609222aSPawel Jakub Dawidek 	{ CAP_MMAP_WX,		"mwx" },
2352609222aSPawel Jakub Dawidek 	{ CAP_MMAP_RWX,		"mma" },
2362609222aSPawel Jakub Dawidek 
2372609222aSPawel Jakub Dawidek 	{ CAP_RECV,		"re" },
2382609222aSPawel Jakub Dawidek 	{ CAP_SEND,		"sd" },
2392609222aSPawel Jakub Dawidek 
2402609222aSPawel Jakub Dawidek 	{ CAP_SOCK_CLIENT,	"scl" },
2412609222aSPawel Jakub Dawidek 	{ CAP_SOCK_SERVER,	"ssr" },
242d57486e2SRobert Watson };
243d57486e2SRobert Watson static const u_int	cap_desc_count = sizeof(cap_desc) /
244d57486e2SRobert Watson 			    sizeof(cap_desc[0]);
245d57486e2SRobert Watson 
246d57486e2SRobert Watson static u_int
247d57486e2SRobert Watson width_capability(cap_rights_t rights)
248d57486e2SRobert Watson {
249d57486e2SRobert Watson 	u_int count, i, width;
250d57486e2SRobert Watson 
251d57486e2SRobert Watson 	count = 0;
252d57486e2SRobert Watson 	width = 0;
253d57486e2SRobert Watson 	for (i = 0; i < cap_desc_count; i++) {
2542609222aSPawel Jakub Dawidek 		if ((cap_desc[i].cd_right & ~rights) == 0) {
255d57486e2SRobert Watson 			width += strlen(cap_desc[i].cd_desc);
256d57486e2SRobert Watson 			if (count)
257d57486e2SRobert Watson 				width++;
258d57486e2SRobert Watson 			count++;
259d57486e2SRobert Watson 		}
260d57486e2SRobert Watson 	}
261d57486e2SRobert Watson 	return (width);
262d57486e2SRobert Watson }
263d57486e2SRobert Watson 
264d57486e2SRobert Watson static void
265d57486e2SRobert Watson print_capability(cap_rights_t rights, u_int capwidth)
266d57486e2SRobert Watson {
267d57486e2SRobert Watson 	u_int count, i, width;
268d57486e2SRobert Watson 
269d57486e2SRobert Watson 	count = 0;
270d57486e2SRobert Watson 	width = 0;
271d57486e2SRobert Watson 	for (i = width_capability(rights); i < capwidth; i++) {
272d57486e2SRobert Watson 		if (rights || i != 0)
273d57486e2SRobert Watson 			printf(" ");
274d57486e2SRobert Watson 		else
275d57486e2SRobert Watson 			printf("-");
276d57486e2SRobert Watson 	}
277d57486e2SRobert Watson 	for (i = 0; i < cap_desc_count; i++) {
2782609222aSPawel Jakub Dawidek 		if ((cap_desc[i].cd_right & ~rights) == 0) {
279d57486e2SRobert Watson 			printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
280d57486e2SRobert Watson 			width += strlen(cap_desc[i].cd_desc);
281d57486e2SRobert Watson 			if (count)
282d57486e2SRobert Watson 				width++;
283d57486e2SRobert Watson 			count++;
284d57486e2SRobert Watson 		}
285d57486e2SRobert Watson 	}
286d57486e2SRobert Watson }
287d57486e2SRobert Watson 
2883d91be41SRobert Watson void
2890daf62d9SStanislav Sedov procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
2903d91be41SRobert Watson {
2910daf62d9SStanislav Sedov 	struct sockstat sock;
2920daf62d9SStanislav Sedov 	struct filestat_list *head;
2930daf62d9SStanislav Sedov 	struct filestat *fst;
2943d91be41SRobert Watson 	const char *str;
2950daf62d9SStanislav Sedov 	struct vnstat vn;
296d57486e2SRobert Watson 	u_int capwidth, width;
2970daf62d9SStanislav Sedov 	int error;
2983d91be41SRobert Watson 
299d57486e2SRobert Watson 	/*
300d57486e2SRobert Watson 	 * To print the header in capability mode, we need to know the width
301d57486e2SRobert Watson 	 * of the widest capability string.  Even if we get no processes
302d57486e2SRobert Watson 	 * back, we will print the header, so we defer aborting due to a lack
303d57486e2SRobert Watson 	 * of processes until after the header logic.
304d57486e2SRobert Watson 	 */
305d57486e2SRobert Watson 	capwidth = 0;
3060daf62d9SStanislav Sedov 	head = procstat_getfiles(procstat, kipp, 0);
307d57486e2SRobert Watson 	if (head != NULL && Cflag) {
308d57486e2SRobert Watson 		STAILQ_FOREACH(fst, head, next) {
309d57486e2SRobert Watson 			width = width_capability(fst->fs_cap_rights);
310d57486e2SRobert Watson 			if (width > capwidth)
311d57486e2SRobert Watson 				capwidth = width;
312d57486e2SRobert Watson 		}
313d57486e2SRobert Watson 		if (capwidth < strlen("CAPABILITIES"))
314d57486e2SRobert Watson 			capwidth = strlen("CAPABILITIES");
315d57486e2SRobert Watson 	}
316d57486e2SRobert Watson 
317d57486e2SRobert Watson 	if (!hflag) {
318d57486e2SRobert Watson 		if (Cflag)
319d57486e2SRobert Watson 			printf("%5s %-16s %4s %1s %-9s %-*s "
320d57486e2SRobert Watson 			    "%-3s %-12s\n", "PID", "COMM", "FD", "T",
321d57486e2SRobert Watson 			    "FLAGS", capwidth, "CAPABILITIES", "PRO",
322d57486e2SRobert Watson 			    "NAME");
323d57486e2SRobert Watson 		else
324d57486e2SRobert Watson 			printf("%5s %-16s %4s %1s %1s %-9s "
325d57486e2SRobert Watson 			    "%3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T",
326d57486e2SRobert Watson 			    "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME");
327d57486e2SRobert Watson 	}
328d57486e2SRobert Watson 
3290daf62d9SStanislav Sedov 	if (head == NULL)
33008afefa8SJoe Marcus Clarke 		return;
3310daf62d9SStanislav Sedov 	STAILQ_FOREACH(fst, head, next) {
3320daf62d9SStanislav Sedov 		printf("%5d ", kipp->ki_pid);
3335a246d29SRobert Watson 		printf("%-16s ", kipp->ki_comm);
3340daf62d9SStanislav Sedov 		if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
3350daf62d9SStanislav Sedov 			printf("ctty ");
3360daf62d9SStanislav Sedov 		else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
337f2805949SJoe Marcus Clarke 			printf(" cwd ");
3380daf62d9SStanislav Sedov 		else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
339f2805949SJoe Marcus Clarke 			printf("jail ");
3400daf62d9SStanislav Sedov 		else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
3410daf62d9SStanislav Sedov 			printf("root ");
3420daf62d9SStanislav Sedov 		else if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
3430daf62d9SStanislav Sedov 			printf("text ");
3440daf62d9SStanislav Sedov 		else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
3450daf62d9SStanislav Sedov 			printf("trace ");
3460daf62d9SStanislav Sedov 		else
3470daf62d9SStanislav Sedov 			printf("%4d ", fst->fs_fd);
348f2805949SJoe Marcus Clarke 
3490daf62d9SStanislav Sedov 		switch (fst->fs_type) {
3500daf62d9SStanislav Sedov 		case PS_FST_TYPE_VNODE:
3513d91be41SRobert Watson 			str = "v";
3523d91be41SRobert Watson 			break;
3533d91be41SRobert Watson 
3540daf62d9SStanislav Sedov 		case PS_FST_TYPE_SOCKET:
3553d91be41SRobert Watson 			str = "s";
3563d91be41SRobert Watson 			break;
3573d91be41SRobert Watson 
3580daf62d9SStanislav Sedov 		case PS_FST_TYPE_PIPE:
3593d91be41SRobert Watson 			str = "p";
3603d91be41SRobert Watson 			break;
3613d91be41SRobert Watson 
3620daf62d9SStanislav Sedov 		case PS_FST_TYPE_FIFO:
3633d91be41SRobert Watson 			str = "f";
3643d91be41SRobert Watson 			break;
3653d91be41SRobert Watson 
3660daf62d9SStanislav Sedov 		case PS_FST_TYPE_KQUEUE:
3673d91be41SRobert Watson 			str = "k";
3683d91be41SRobert Watson 			break;
3693d91be41SRobert Watson 
3700daf62d9SStanislav Sedov 		case PS_FST_TYPE_CRYPTO:
3713d91be41SRobert Watson 			str = "c";
3723d91be41SRobert Watson 			break;
3733d91be41SRobert Watson 
3740daf62d9SStanislav Sedov 		case PS_FST_TYPE_MQUEUE:
3753d91be41SRobert Watson 			str = "m";
3763d91be41SRobert Watson 			break;
3773d91be41SRobert Watson 
3780daf62d9SStanislav Sedov 		case PS_FST_TYPE_SHM:
37987cb56f6SRobert Watson 			str = "h";
38087cb56f6SRobert Watson 			break;
38187cb56f6SRobert Watson 
3820daf62d9SStanislav Sedov 		case PS_FST_TYPE_PTS:
383bc093719SEd Schouten 			str = "t";
384bc093719SEd Schouten 			break;
385bc093719SEd Schouten 
3860daf62d9SStanislav Sedov 		case PS_FST_TYPE_SEM:
3876bc1e9cdSJohn Baldwin 			str = "e";
3886bc1e9cdSJohn Baldwin 			break;
3896bc1e9cdSJohn Baldwin 
3900daf62d9SStanislav Sedov 		case PS_FST_TYPE_NONE:
3910daf62d9SStanislav Sedov 		case PS_FST_TYPE_UNKNOWN:
3923d91be41SRobert Watson 		default:
3933d91be41SRobert Watson 			str = "?";
3943d91be41SRobert Watson 			break;
3953d91be41SRobert Watson 		}
3963d91be41SRobert Watson 		printf("%1s ", str);
397d57486e2SRobert Watson 		if (!Cflag) {
3983d91be41SRobert Watson 			str = "-";
3990daf62d9SStanislav Sedov 			if (fst->fs_type == PS_FST_TYPE_VNODE) {
400d57486e2SRobert Watson 				error = procstat_get_vnode_info(procstat, fst,
401d57486e2SRobert Watson 				    &vn, NULL);
4020daf62d9SStanislav Sedov 				switch (vn.vn_type) {
4030daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VREG:
4043d91be41SRobert Watson 					str = "r";
4053d91be41SRobert Watson 					break;
4063d91be41SRobert Watson 
4070daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VDIR:
4083d91be41SRobert Watson 					str = "d";
4093d91be41SRobert Watson 					break;
4103d91be41SRobert Watson 
4110daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VBLK:
4123d91be41SRobert Watson 					str = "b";
4133d91be41SRobert Watson 					break;
4143d91be41SRobert Watson 
4150daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VCHR:
4163d91be41SRobert Watson 					str = "c";
4173d91be41SRobert Watson 					break;
4183d91be41SRobert Watson 
4190daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VLNK:
4203d91be41SRobert Watson 					str = "l";
4213d91be41SRobert Watson 					break;
4223d91be41SRobert Watson 
4230daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VSOCK:
4243d91be41SRobert Watson 					str = "s";
4253d91be41SRobert Watson 					break;
4263d91be41SRobert Watson 
4270daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VFIFO:
4283d91be41SRobert Watson 					str = "f";
4293d91be41SRobert Watson 					break;
4303d91be41SRobert Watson 
4310daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VBAD:
4323d91be41SRobert Watson 					str = "x";
4333d91be41SRobert Watson 					break;
4343d91be41SRobert Watson 
4350daf62d9SStanislav Sedov 				case PS_FST_VTYPE_VNON:
4360daf62d9SStanislav Sedov 				case PS_FST_VTYPE_UNKNOWN:
4373d91be41SRobert Watson 				default:
4383d91be41SRobert Watson 					str = "?";
4393d91be41SRobert Watson 					break;
4403d91be41SRobert Watson 				}
4413d91be41SRobert Watson 			}
4423d91be41SRobert Watson 			printf("%1s ", str);
443d57486e2SRobert Watson 		}
4440daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-");
4450daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-");
4460daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-");
4470daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-");
4480daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-");
4490daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-");
4500daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
4510daf62d9SStanislav Sedov 		printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
452d57486e2SRobert Watson 		if (!Cflag) {
4530daf62d9SStanislav Sedov 			if (fst->fs_ref_count > -1)
4540daf62d9SStanislav Sedov 				printf("%3d ", fst->fs_ref_count);
455f2805949SJoe Marcus Clarke 			else
456f2805949SJoe Marcus Clarke 				printf("%3c ", '-');
4570daf62d9SStanislav Sedov 			if (fst->fs_offset > -1)
4580daf62d9SStanislav Sedov 				printf("%7jd ", (intmax_t)fst->fs_offset);
459f2805949SJoe Marcus Clarke 			else
460f2805949SJoe Marcus Clarke 				printf("%7c ", '-');
461d57486e2SRobert Watson 		}
462d57486e2SRobert Watson 		if (Cflag) {
463d57486e2SRobert Watson 			print_capability(fst->fs_cap_rights, capwidth);
464d57486e2SRobert Watson 			printf(" ");
465d57486e2SRobert Watson 		}
4660daf62d9SStanislav Sedov 		switch (fst->fs_type) {
4670daf62d9SStanislav Sedov 		case PS_FST_TYPE_SOCKET:
4680daf62d9SStanislav Sedov 			error = procstat_get_socket_info(procstat, fst, &sock, NULL);
4690daf62d9SStanislav Sedov 			if (error != 0)
4700daf62d9SStanislav Sedov 				break;
4715a246d29SRobert Watson 			printf("%-3s ",
4720daf62d9SStanislav Sedov 			    protocol_to_string(sock.dom_family,
4730daf62d9SStanislav Sedov 			    sock.type, sock.proto));
4743d91be41SRobert Watson 			/*
4753d91be41SRobert Watson 			 * While generally we like to print two addresses,
4763d91be41SRobert Watson 			 * local and peer, for sockets, it turns out to be
4773d91be41SRobert Watson 			 * more useful to print the first non-nul address for
4783d91be41SRobert Watson 			 * local sockets, as typically they aren't bound and
4793d91be41SRobert Watson 			 *  connected, and the path strings can get long.
4803d91be41SRobert Watson 			 */
4810daf62d9SStanislav Sedov 			if (sock.dom_family == AF_LOCAL) {
4823d91be41SRobert Watson 				struct sockaddr_un *sun =
4830daf62d9SStanislav Sedov 				    (struct sockaddr_un *)&sock.sa_local;
4843d91be41SRobert Watson 
4853d91be41SRobert Watson 				if (sun->sun_path[0] != 0)
4860daf62d9SStanislav Sedov 					print_address(&sock.sa_local);
4873d91be41SRobert Watson 				else
4880daf62d9SStanislav Sedov 					print_address(&sock.sa_peer);
4893d91be41SRobert Watson 			} else {
4900daf62d9SStanislav Sedov 				print_address(&sock.sa_local);
4913d91be41SRobert Watson 				printf(" ");
4920daf62d9SStanislav Sedov 				print_address(&sock.sa_peer);
4933d91be41SRobert Watson 			}
4943d91be41SRobert Watson 			break;
4953d91be41SRobert Watson 
4963d91be41SRobert Watson 		default:
497e506e182SJohn Baldwin 			printf("%-3s ", "-");
498e506e182SJohn Baldwin 			printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-");
4993d91be41SRobert Watson 		}
5003d91be41SRobert Watson 
5013d91be41SRobert Watson 		printf("\n");
5023d91be41SRobert Watson 	}
50339f6ca65SMikolaj Golub 	procstat_freefiles(procstat, head);
5043d91be41SRobert Watson }
505