Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jun 2014 13:22:02 GMT
From:      zkorchev@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r269005 - soc2014/zkorchev/freebsd_head/usr.bin/fstat
Message-ID:  <201406031322.s53DM2e5092466@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zkorchev
Date: Tue Jun  3 13:22:02 2014
New Revision: 269005
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=269005

Log:
  fstat JSON output

Modified:
  soc2014/zkorchev/freebsd_head/usr.bin/fstat/Makefile
  soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.1
  soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.c

Modified: soc2014/zkorchev/freebsd_head/usr.bin/fstat/Makefile
==============================================================================
--- soc2014/zkorchev/freebsd_head/usr.bin/fstat/Makefile	Tue Jun  3 10:56:55 2014	(r269004)
+++ soc2014/zkorchev/freebsd_head/usr.bin/fstat/Makefile	Tue Jun  3 13:22:02 2014	(r269005)
@@ -5,7 +5,8 @@
 SRCS=	fstat.c fuser.c main.c
 LINKS=	${BINDIR}/fstat ${BINDIR}/fuser
 DPADD=	${LIBKVM} ${LIBUTIL} ${LIBPROCSTAT}
-LDADD=	-lkvm -lutil -lprocstat
+LDADD=	-lkvm -lutil -lprocstat -lsol
+CFLAGS+=	-DSOL_ON -I/usr/local/include
 
 MAN1=	fuser.1 fstat.1
 

Modified: soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.1
==============================================================================
--- soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.1	Tue Jun  3 10:56:55 2014	(r269004)
+++ soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.1	Tue Jun  3 13:22:02 2014	(r269005)
@@ -71,6 +71,8 @@
 .It Fl N
 Extract the name list from the specified system instead of the default,
 which is the kernel image the system has booted from.
+.It Fl O
+Output the results in JSON format.
 .It Fl m
 Include memory-mapped files in the listing; normally these are excluded
 due to the extra processing required.

Modified: soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.c
==============================================================================
--- soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.c	Tue Jun  3 10:56:55 2014	(r269004)
+++ soc2014/zkorchev/freebsd_head/usr.bin/fstat/fstat.c	Tue Jun  3 13:22:02 2014	(r269005)
@@ -54,6 +54,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <netdb.h>
+#include <sol.h>
 
 #include "functions.h"
 
@@ -64,6 +65,7 @@
 static int	nflg;	/* (numerical) display f.s. and rdev as dev_t */
 static int	mflg;	/* include memory-mapped files */
 static int	vflg;	/* be verbose */
+static int	Oflg;	/* use JSON as output format */
 
 typedef struct devs {
 	struct devs	*next;
@@ -75,6 +77,8 @@
 static DEVS *devs;
 static char *memf, *nlistf;
 
+static struct sol_stream sol_stream;
+
 static int	getfname(const char *filename);
 static void	dofiles(struct procstat *procstat, struct kinfo_proc *p);
 static void	print_access_flags(int flags);
@@ -103,10 +107,14 @@
 	int arg, ch, what;
 	int cnt, i;
 
+	/* prevent unused variable warnings */
+	(void)sol_stream;
+	(void)Oflg;
+
 	arg = 0;
 	what = KERN_PROC_PROC;
 	nlistf = memf = NULL;
-	while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1)
+	while ((ch = getopt(argc, argv, "fmnp:u:vN:M:O")) != -1)
 		switch((char)ch) {
 		case 'f':
 			fsflg = 1;
@@ -144,6 +152,13 @@
 		case 'v':
 			vflg = 1;
 			break;
+		case 'O':
+#if defined(SOL_ON)
+			Oflg = 1;
+#else
+			errx(1, "compiled without -O support");
+#endif
+			break;
 		case '?':
 		default:
 			usage();
@@ -175,19 +190,29 @@
 	if (p == NULL)
 		errx(1, "procstat_getprocs()");
 
-	/*
-	 * Print header.
-	 */
-	if (nflg)
-		printf("%s",
-"USER     CMD          PID   FD  DEV    INUM       MODE SZ|DV R/W");
-	else
-		printf("%s",
-"USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W");
-	if (checkfile && fsflg == 0)
-		printf(" NAME\n");
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		sol_init(&sol_stream, SOL_JSON);
+		sol_array_start(&sol_stream);
+	}
 	else
-		putchar('\n');
+#endif
+	{
+		/*
+		 * Print header.
+		 */
+		if (nflg)
+			printf("%s",
+	"USER     CMD          PID   FD  DEV    INUM       MODE SZ|DV R/W");
+		else
+			printf("%s",
+	"USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W");
+		if (checkfile && fsflg == 0)
+			printf(" NAME\n");
+		else
+			putchar('\n');
+	}
 
 	/*
 	 * Go through the process list.
@@ -197,6 +222,14 @@
 			continue;
 		dofiles(procstat, &p[i]);
 	}
+
+#if defined(SOL_ON)
+	if (Oflg) {
+		sol_array_end(&sol_stream);
+		sol_term(&sol_stream);
+	}
+#endif
+
 	procstat_freeprocs(procstat, p);
 	procstat_close(procstat);
 	return (0);
@@ -218,8 +251,17 @@
 	head = procstat_getfiles(procstat, kp, mflg);
 	if (head == NULL)
 		return;
-	STAILQ_FOREACH(fst, head, next)
-		print_file_info(procstat, fst, uname, cmd, pid);
+	STAILQ_FOREACH(fst, head, next) {
+#if defined(SOL_ON)
+		if (Oflg) {
+			sol_map_start(&sol_stream);
+			print_file_info(procstat, fst, uname, cmd, pid);
+			sol_map_end(&sol_stream);
+		}
+		else
+#endif
+			print_file_info(procstat, fst, uname, cmd, pid);
+	}
 	procstat_freefiles(procstat, head);
 }
 
@@ -255,26 +297,60 @@
 			return;
 	}
 
-	/*
-	 * Print entry prefix.
-	 */
-	printf("%-8.8s %-10s %5d", uname, cmd, pid);
-	if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
-		printf(" text");
-	else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
-		printf("   wd");
-	else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
-		printf(" root");
-	else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
-		printf("   tr");
-	else if (fst->fs_uflags & PS_FST_UFLAG_MMAP)
-		printf(" mmap");
-	else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
-		printf(" jail");
-	else if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
-		printf(" ctty");
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		sol_map_key(&sol_stream, "user", 4);
+		sol_string(&sol_stream, uname, strlen(uname));
+
+		sol_map_key(&sol_stream, "cmd", 3);
+		sol_string(&sol_stream, cmd, strlen(cmd));
+
+		sol_map_key(&sol_stream, "pid", 3);
+		sol_integer(&sol_stream, pid);
+
+		sol_map_key(&sol_stream, "fd", 2);
+		if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
+			sol_string(&sol_stream, "text", 4);
+		else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
+			sol_string(&sol_stream, "wd", 2);
+		else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
+			sol_string(&sol_stream, "root", 4);
+		else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
+			sol_string(&sol_stream, "tr", 2);
+		else if (fst->fs_uflags & PS_FST_UFLAG_MMAP)
+			sol_string(&sol_stream, "mmap", 4);
+		else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
+			sol_string(&sol_stream, "jail", 4);
+		else if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
+			sol_string(&sol_stream, "ctty", 4);
+		else
+			sol_integer(&sol_stream, fst->fs_fd);
+	}
 	else
-		printf(" %4d", fst->fs_fd);
+#endif
+	{
+		/*
+		 * Print entry prefix.
+		 */
+		printf("%-8.8s %-10s %5d", uname, cmd, pid);
+		if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
+			printf(" text");
+		else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
+			printf("   wd");
+		else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
+			printf(" root");
+		else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
+			printf("   tr");
+		else if (fst->fs_uflags & PS_FST_UFLAG_MMAP)
+			printf(" mmap");
+		else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
+			printf(" jail");
+		else if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
+			printf(" ctty");
+		else
+			printf(" %4d", fst->fs_fd);
+	}
 
 	/*
 	 * Print type-specific data.
@@ -305,9 +381,17 @@
 			    "unknown file type %d for file %d of pid %d\n",
 			    fst->fs_type, fst->fs_fd, pid);
 	}
-	if (filename && !fsflg)
-		printf("  %s", filename);
-	putchar('\n');
+	if (filename && !fsflg) {
+#if defined(SOL_ON)
+		if (Oflg) {
+			sol_map_key(&sol_stream, "name", 4);
+			sol_string(&sol_stream, filename, strlen(filename));
+		}
+		else
+#endif
+			printf("  %s", filename);
+	}
+	if (!Oflg) putchar('\n');
 }
 
 static void
@@ -330,13 +414,29 @@
 
 	error = procstat_get_socket_info(procstat, fst, &sock, errbuf);
 	if (error != 0) {
-		printf("* error");
+		if (!Oflg) printf("* error");
 		return;
 	}
-	if (sock.type > STYPEMAX)
-		printf("* %s ?%d", sock.dname, sock.type);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		sol_map_key(&sol_stream, "socket", 6);
+		sol_string(&sol_stream, sock.dname, strlen(sock.dname));
+
+		sol_map_key(&sol_stream, "type", 4);
+		if (sock.type > STYPEMAX)
+			sol_integer(&sol_stream, sock.type);
+		else
+			sol_string(&sol_stream, stypename[sock.type], strlen(stypename[sock.type]));
+	}
 	else
-		printf("* %s %s", sock.dname, stypename[sock.type]);
+#endif
+	{
+		if (sock.type > STYPEMAX)
+			printf("* %s ?%d", sock.dname, sock.type);
+		else
+			printf("* %s %s", sock.dname, stypename[sock.type]);
+	}
 
 	/*
 	 * protocol specific formatting
@@ -354,21 +454,52 @@
 	case AF_INET6:
 		if (!isopen)
 			setprotoent(++isopen);
-		if ((pe = getprotobynumber(sock.proto)) != NULL)
-			printf(" %s", pe->p_name);
+#if defined(SOL_ON)
+		if (Oflg)
+		{
+			sol_map_key(&sol_stream, "proto", 5);
+			if ((pe = getprotobynumber(sock.proto)) != NULL)
+				sol_string(&sol_stream, pe->p_name, strlen(pe->p_name));
+			else
+				sol_integer(&sol_stream, sock.proto);
+			if (sock.proto == IPPROTO_TCP ) {
+				if (sock.inp_ppcb != 0) {
+					sol_map_key(&sol_stream, "ppcb", 4);
+					sol_integer(&sol_stream, sock.inp_ppcb); // TODO hex?
+				}
+			}
+			else if (sock.so_pcb != 0) {
+				sol_map_key(&sol_stream, "pcb", 3);
+				sol_integer(&sol_stream, sock.so_pcb); // TODO hex?
+			}
+		}
 		else
-			printf(" %d", sock.proto);
-		if (sock.proto == IPPROTO_TCP ) {
-			if (sock.inp_ppcb != 0)
-				printf(" %lx", (u_long)sock.inp_ppcb);
+#endif
+		{
+			if ((pe = getprotobynumber(sock.proto)) != NULL)
+				printf(" %s", pe->p_name);
+			else
+				printf(" %d", sock.proto);
+			if (sock.proto == IPPROTO_TCP ) {
+				if (sock.inp_ppcb != 0)
+					printf(" %lx", (u_long)sock.inp_ppcb);
+			}
+			else if (sock.so_pcb != 0)
+				printf(" %lx", (u_long)sock.so_pcb);
 		}
-		else if (sock.so_pcb != 0)
-			printf(" %lx", (u_long)sock.so_pcb);
 		break;
 	case AF_UNIX:
 		/* print address of pcb and connected pcb */
 		if (sock.so_pcb != 0) {
-			printf(" %lx", (u_long)sock.so_pcb);
+#if defined(SOL_ON)
+			if (Oflg) {
+				sol_map_key(&sol_stream, "pcb", 3);
+				sol_integer(&sol_stream, sock.so_pcb); // TODO hex?
+			}
+			else
+#endif
+				printf(" %lx", (u_long)sock.so_pcb);
+
 			if (sock.unp_conn) {
 				char shoconn[4], *cp;
 
@@ -379,14 +510,31 @@
 				if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE))
 					*cp++ = '>';
 				*cp = '\0';
-				printf(" %s %lx", shoconn,
-				    (u_long)sock.unp_conn);
-                        }
+#if defined(SOL_ON)
+				if (Oflg) {
+					sol_map_key(&sol_stream, "flow", 4);
+					sol_string(&sol_stream, shoconn, cp - shoconn);
+					sol_map_key(&sol_stream, "conn", 4);
+					sol_integer(&sol_stream, sock.unp_conn); // TODO hex?
+				}
+				else
+#endif
+					printf(" %s %lx", shoconn, (u_long)sock.unp_conn);
+			}
 		}
 		break;
 	default:
 		/* print protocol number and socket address */
-		printf(" %d %lx", sock.proto, (u_long)sock.so_addr);
+#if defined(SOL_ON)
+		if (Oflg) {
+			sol_map_key(&sol_stream, "proto", 5);
+			sol_integer(&sol_stream, sock.proto);
+			sol_map_key(&sol_stream, "address", 7);
+			sol_integer(&sol_stream, sock.so_addr);
+		}
+		else
+#endif
+			printf(" %d %lx", sock.proto, (u_long)sock.so_addr);
 	}
 }
 
@@ -399,11 +547,24 @@
 
 	error = procstat_get_pipe_info(procstat, fst, &ps, errbuf);
 	if (error != 0) {
-		printf("* error");
+		if (!Oflg) printf("* error");
 		return;
 	}
-	printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer);
-	printf(" %6zd", ps.buffer_cnt);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		sol_map_key(&sol_stream, "pipe", 4);
+		sol_array_start(&sol_stream);
+		sol_integer(&sol_stream, (u_long)ps.addr);
+		sol_integer(&sol_stream, (u_long)ps.peer);
+		sol_array_end(&sol_stream);
+	}
+	else
+#endif
+	{
+		printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer);
+		printf(" %6zd", ps.buffer_cnt);
+	}
 	print_access_flags(fst->fs_fflags);
 }
 
@@ -416,14 +577,29 @@
 
 	error = procstat_get_pts_info(procstat, fst, &pts, errbuf);
 	if (error != 0) {
-		printf("* error");
+		if (!Oflg) printf("* error");
 		return;
 	}
-	printf("* pseudo-terminal master ");
-	if (nflg || !*pts.devname) {
-		printf("%#10jx", (uintmax_t)pts.dev);
-	} else {
-		printf("%10s", pts.devname);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		if (nflg || !*pts.devname) {
+			sol_map_key(&sol_stream, "ptm", 3);
+			sol_integer(&sol_stream, pts.dev);
+		} else {
+			sol_map_key(&sol_stream, "ptmname", 7);
+			sol_string(&sol_stream, pts.devname, strlen(pts.devname));
+		}
+	}
+	else
+#endif
+	{
+		printf("* pseudo-terminal master ");
+		if (nflg || !*pts.devname) {
+			printf("%#10jx", (uintmax_t)pts.dev);
+		} else {
+			printf("%10s", pts.devname);
+		}
 	}
 	print_access_flags(fst->fs_fflags);
 }
@@ -438,17 +614,39 @@
 
 	error = procstat_get_sem_info(procstat, fst, &sem, errbuf);
 	if (error != 0) {
-		printf("* error");
+		if (!Oflg) printf("* error");
 		return;
 	}
-	if (nflg) {
-		printf("             ");
-		(void)snprintf(mode, sizeof(mode), "%o", sem.mode);
-	} else {
-		printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
-		strmode(sem.mode, mode);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		if (nflg) {
+			(void)snprintf(mode, sizeof(mode), "%o", sem.mode);
+		}
+		else {
+			if (fst->fs_path) {
+				sol_map_key(&sol_stream, "path", 4);
+				sol_string(&sol_stream, fst->fs_path, strlen(fst->fs_path));
+			}
+			strmode(sem.mode, mode);
+		}
+		sol_map_key(&sol_stream, "mode", 4);
+		sol_string(&sol_stream, mode, strlen(mode));
+		sol_map_key(&sol_stream, "sem", 3);
+		sol_integer(&sol_stream, sem.value);
+	}
+	else
+#endif
+	{
+		if (nflg) {
+			printf("             ");
+			(void)snprintf(mode, sizeof(mode), "%o", sem.mode);
+		} else {
+			printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
+			strmode(sem.mode, mode);
+		}
+		printf(" %10s %6u", mode, sem.value);
 	}
-	printf(" %10s %6u", mode, sem.value);
 	print_access_flags(fst->fs_fflags);
 }
 
@@ -462,17 +660,39 @@
 
 	error = procstat_get_shm_info(procstat, fst, &shm, errbuf);
 	if (error != 0) {
-		printf("* error");
+		if (!Oflg) printf("* error");
 		return;
 	}
-	if (nflg) {
-		printf("             ");
-		(void)snprintf(mode, sizeof(mode), "%o", shm.mode);
-	} else {
-		printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
-		strmode(shm.mode, mode);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		if (nflg) {
+			(void)snprintf(mode, sizeof(mode), "%o", shm.mode);
+		}
+		else {
+			if (fst->fs_path) {
+				sol_map_key(&sol_stream, "path", 4);
+				sol_string(&sol_stream, fst->fs_path, strlen(fst->fs_path));
+			}
+			strmode(shm.mode, mode);
+		}
+		sol_map_key(&sol_stream, "mode", 4);
+		sol_string(&sol_stream, mode, strlen(mode));
+		sol_map_key(&sol_stream, "shmsize", 7);
+		sol_integer(&sol_stream, shm.size);
+	}
+	else
+#endif
+	{
+		if (nflg) {
+			printf("             ");
+			(void)snprintf(mode, sizeof(mode), "%o", shm.mode);
+		} else {
+			printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
+			strmode(shm.mode, mode);
+		}
+		printf(" %10s %6ju", mode, shm.size);
 	}
-	printf(" %10s %6ju", mode, shm.size);
 	print_access_flags(fst->fs_fflags);
 }
 
@@ -494,14 +714,36 @@
 	else if (vn.vn_type == PS_FST_VTYPE_VNON)
 		badtype = "none";
 	if (badtype != NULL) {
-		printf(" -         -  %10s    -", badtype);
+#if defined(SOL_ON)
+		if (Oflg) {
+			sol_map_key(&sol_stream, "mode", 4);
+			sol_string(&sol_stream, badtype, strlen(badtype));
+		}
+		else
+#endif
+			printf(" -         -  %10s    -", badtype);
 		return;
 	}
 
-	if (nflg)
-		printf(" %#5jx", (uintmax_t)vn.vn_fsid);
-	else if (vn.vn_mntdir != NULL)
-		(void)printf(" %-8s", vn.vn_mntdir);
+#if defined(SOL_ON)
+	if (Oflg) {
+		if (nflg) {
+			sol_map_key(&sol_stream, "dev", 3);
+			sol_integer(&sol_stream, vn.vn_fsid); // TODO hex?
+		}
+		else if (vn.vn_mntdir != NULL) {
+			sol_map_key(&sol_stream, "mount", 5);
+			sol_string(&sol_stream, vn.vn_mntdir, strlen(vn.vn_mntdir));
+		}
+	}
+	else
+#endif
+	{
+		if (nflg)
+			printf(" %#5jx", (uintmax_t)vn.vn_fsid);
+		else if (vn.vn_mntdir != NULL)
+			(void)printf(" %-8s", vn.vn_mntdir);
+	}
 
 	/*
 	 * Print access mode.
@@ -511,16 +753,48 @@
 	else {
 		strmode(vn.vn_mode, mode);
 	}
-	(void)printf(" %6jd %10s", (intmax_t)vn.vn_fileid, mode);
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		sol_map_key(&sol_stream, "inode", 5);
+		sol_integer(&sol_stream, vn.vn_fileid);
 
-	if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
-		if (nflg || !*vn.vn_devname)
-			printf(" %#6jx", (uintmax_t)vn.vn_dev);
-		else {
-			printf(" %6s", vn.vn_devname);
-		}
-	} else
-		printf(" %6ju", (uintmax_t)vn.vn_size);
+		sol_map_key(&sol_stream, "mode", 4);
+		sol_string(&sol_stream, mode, strlen(mode));
+	}
+	else
+#endif
+		(void)printf(" %6jd %10s", (intmax_t)vn.vn_fileid, mode);
+
+#if defined(SOL_ON)
+	if (Oflg)
+	{
+		if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
+			if (nflg || !*vn.vn_devname) {
+				sol_map_key(&sol_stream, "dev", 3);
+				sol_integer(&sol_stream, vn.vn_dev); // TODO hex?
+			}
+			else {
+				sol_map_key(&sol_stream, "devname", 7);
+				sol_string(&sol_stream, vn.vn_devname, strlen(vn.vn_devname));
+			}
+		} else
+			sol_map_key(&sol_stream, "size", 4);
+			sol_integer(&sol_stream, vn.vn_size);
+	}
+	else
+	{
+#endif
+		if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
+			if (nflg || !*vn.vn_devname) {
+				printf(" %#6jx", (uintmax_t)vn.vn_dev);
+			}
+			else {
+				printf(" %6s", vn.vn_devname);
+			}
+		} else
+			printf(" %6ju", (uintmax_t)vn.vn_size);
+	}
 	print_access_flags(fst->fs_fflags);
 }
 
@@ -534,7 +808,14 @@
 		strcat(rw, "r");
 	if (flags & PS_FST_FFLAG_WRITE)
 		strcat(rw, "w");
-	printf(" %2s", rw);
+#if defined(SOL_ON)
+	if (Oflg) {
+		sol_map_key(&sol_stream, "r/w", 3);
+		sol_string(&sol_stream, rw, strlen(rw));
+	}
+	else
+#endif
+		printf(" %2s", rw);
 }
 
 int
@@ -562,6 +843,6 @@
 usage(void)
 {
 	(void)fprintf(stderr,
- "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [file ...]\n");
+ "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [-O] [file ...]\n");
 	exit(1);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406031322.s53DM2e5092466>