19b50d902SRodney W. Grimes /*- 20daf62d9SStanislav Sedov * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org> 39b50d902SRodney W. Grimes * Copyright (c) 1988, 1993 49b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 59b50d902SRodney W. Grimes * 69b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 79b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 89b50d902SRodney W. Grimes * are met: 99b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 109b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 119b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 129b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 139b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 14*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 159b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 169b50d902SRodney W. Grimes * without specific prior written permission. 179b50d902SRodney W. Grimes * 189b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 199b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 209b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 219b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 229b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 239b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 249b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 259b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 269b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 279b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 289b50d902SRodney W. Grimes * SUCH DAMAGE. 299b50d902SRodney W. Grimes */ 309b50d902SRodney W. Grimes 31e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 32e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #include <sys/param.h> 359b50d902SRodney W. Grimes #include <sys/user.h> 369b50d902SRodney W. Grimes #include <sys/stat.h> 379b50d902SRodney W. Grimes #include <sys/socket.h> 389b50d902SRodney W. Grimes #include <sys/socketvar.h> 399b50d902SRodney W. Grimes #include <sys/sysctl.h> 40d2bccb9fSDavid Greenman #include <sys/queue.h> 419b50d902SRodney W. Grimes 429b50d902SRodney W. Grimes #include <netinet/in.h> 439b50d902SRodney W. Grimes 440daf62d9SStanislav Sedov #include <assert.h> 459b50d902SRodney W. Grimes #include <ctype.h> 46c1e65942SPhilippe Charnier #include <err.h> 470daf62d9SStanislav Sedov #include <libprocstat.h> 48df3f5d9dSPeter Wemm #include <limits.h> 499b50d902SRodney W. Grimes #include <pwd.h> 5076db9ccfSWarner Losh #include <stdint.h> 519b50d902SRodney W. Grimes #include <stdio.h> 529b50d902SRodney W. Grimes #include <stdlib.h> 5305427aafSKonstantin Belousov #include <stddef.h> 549b50d902SRodney W. Grimes #include <string.h> 55df3f5d9dSPeter Wemm #include <unistd.h> 560b7a57ddSRuslan Ermilov #include <netdb.h> 579b50d902SRodney W. Grimes 580daf62d9SStanislav Sedov #include "functions.h" 599b50d902SRodney W. Grimes 60357050fcSEd Schouten static int fsflg, /* show files on same filesystem as file(s) argument */ 619b50d902SRodney W. Grimes pflg, /* show files open by a particular pid */ 629b50d902SRodney W. Grimes uflg; /* show files open by a particular (effective) user */ 63357050fcSEd Schouten static int checkfile; /* restrict to particular files or filesystems */ 64357050fcSEd Schouten static int nflg; /* (numerical) display f.s. and rdev as dev_t */ 65357050fcSEd Schouten static int mflg; /* include memory-mapped files */ 66357050fcSEd Schouten static int vflg; /* be verbose */ 679b50d902SRodney W. Grimes 680daf62d9SStanislav Sedov typedef struct devs { 690daf62d9SStanislav Sedov struct devs *next; 700daf62d9SStanislav Sedov uint32_t fsid; 710daf62d9SStanislav Sedov uint64_t ino; 720daf62d9SStanislav Sedov const char *name; 730daf62d9SStanislav Sedov } DEVS; 749b50d902SRodney W. Grimes 75357050fcSEd Schouten static DEVS *devs; 76357050fcSEd Schouten static char *memf, *nlistf; 779b50d902SRodney W. Grimes 780daf62d9SStanislav Sedov static int getfname(const char *filename); 790daf62d9SStanislav Sedov static void dofiles(struct procstat *procstat, struct kinfo_proc *p); 800daf62d9SStanislav Sedov static void print_access_flags(int flags); 810daf62d9SStanislav Sedov static void print_file_info(struct procstat *procstat, 820daf62d9SStanislav Sedov struct filestat *fst, const char *uname, const char *cmd, int pid); 830daf62d9SStanislav Sedov static void print_pipe_info(struct procstat *procstat, 840daf62d9SStanislav Sedov struct filestat *fst); 850daf62d9SStanislav Sedov static void print_pts_info(struct procstat *procstat, 860daf62d9SStanislav Sedov struct filestat *fst); 87958aa575SJohn Baldwin static void print_sem_info(struct procstat *procstat, 88958aa575SJohn Baldwin struct filestat *fst); 89e506e182SJohn Baldwin static void print_shm_info(struct procstat *procstat, 90e506e182SJohn Baldwin struct filestat *fst); 910daf62d9SStanislav Sedov static void print_socket_info(struct procstat *procstat, 920daf62d9SStanislav Sedov struct filestat *fst); 930daf62d9SStanislav Sedov static void print_vnode_info(struct procstat *procstat, 940daf62d9SStanislav Sedov struct filestat *fst); 950daf62d9SStanislav Sedov static void usage(void) __dead2; 961c17fc99SPeter Wemm 971c17fc99SPeter Wemm int 980daf62d9SStanislav Sedov do_fstat(int argc, char **argv) 999b50d902SRodney W. Grimes { 1000daf62d9SStanislav Sedov struct kinfo_proc *p; 10127d57ea9SDavid Malone struct passwd *passwd; 1020daf62d9SStanislav Sedov struct procstat *procstat; 1039b50d902SRodney W. Grimes int arg, ch, what; 1040daf62d9SStanislav Sedov int cnt, i; 1059b50d902SRodney W. Grimes 1069b50d902SRodney W. Grimes arg = 0; 107f9feee17SEd Maste what = KERN_PROC_PROC; 1089b50d902SRodney W. Grimes nlistf = memf = NULL; 109d0482be8SBrian Feldman while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1) 1109b50d902SRodney W. Grimes switch((char)ch) { 1119b50d902SRodney W. Grimes case 'f': 1129b50d902SRodney W. Grimes fsflg = 1; 1139b50d902SRodney W. Grimes break; 1149b50d902SRodney W. Grimes case 'M': 1159b50d902SRodney W. Grimes memf = optarg; 1169b50d902SRodney W. Grimes break; 1179b50d902SRodney W. Grimes case 'N': 1189b50d902SRodney W. Grimes nlistf = optarg; 1199b50d902SRodney W. Grimes break; 120d0482be8SBrian Feldman case 'm': 121d0482be8SBrian Feldman mflg = 1; 122d0482be8SBrian Feldman break; 1239b50d902SRodney W. Grimes case 'n': 1249b50d902SRodney W. Grimes nflg = 1; 1259b50d902SRodney W. Grimes break; 1269b50d902SRodney W. Grimes case 'p': 1279b50d902SRodney W. Grimes if (pflg++) 1289b50d902SRodney W. Grimes usage(); 1299b50d902SRodney W. Grimes if (!isdigit(*optarg)) { 130c1e65942SPhilippe Charnier warnx("-p requires a process id"); 1319b50d902SRodney W. Grimes usage(); 1329b50d902SRodney W. Grimes } 1339b50d902SRodney W. Grimes what = KERN_PROC_PID; 1349b50d902SRodney W. Grimes arg = atoi(optarg); 1359b50d902SRodney W. Grimes break; 1369b50d902SRodney W. Grimes case 'u': 1379b50d902SRodney W. Grimes if (uflg++) 1389b50d902SRodney W. Grimes usage(); 139c1e65942SPhilippe Charnier if (!(passwd = getpwnam(optarg))) 140c1e65942SPhilippe Charnier errx(1, "%s: unknown uid", optarg); 1419b50d902SRodney W. Grimes what = KERN_PROC_UID; 1429b50d902SRodney W. Grimes arg = passwd->pw_uid; 1439b50d902SRodney W. Grimes break; 1449b50d902SRodney W. Grimes case 'v': 1459b50d902SRodney W. Grimes vflg = 1; 1469b50d902SRodney W. Grimes break; 1479b50d902SRodney W. Grimes case '?': 1489b50d902SRodney W. Grimes default: 1499b50d902SRodney W. Grimes usage(); 1509b50d902SRodney W. Grimes } 1519b50d902SRodney W. Grimes 1529b50d902SRodney W. Grimes if (*(argv += optind)) { 1539b50d902SRodney W. Grimes for (; *argv; ++argv) { 1549b50d902SRodney W. Grimes if (getfname(*argv)) 1559b50d902SRodney W. Grimes checkfile = 1; 1569b50d902SRodney W. Grimes } 157487ac9acSUlrich Spörlein if (!checkfile) /* file(s) specified, but none accessible */ 1589b50d902SRodney W. Grimes exit(1); 1599b50d902SRodney W. Grimes } 1609b50d902SRodney W. Grimes 1619b50d902SRodney W. Grimes if (fsflg && !checkfile) { 1629b50d902SRodney W. Grimes /* -f with no files means use wd */ 1639b50d902SRodney W. Grimes if (getfname(".") == 0) 1649b50d902SRodney W. Grimes exit(1); 1659b50d902SRodney W. Grimes checkfile = 1; 1669b50d902SRodney W. Grimes } 1679b50d902SRodney W. Grimes 1681f910d6cSDag-Erling Smørgrav if (memf != NULL) 1690daf62d9SStanislav Sedov procstat = procstat_open_kvm(nlistf, memf); 1701f910d6cSDag-Erling Smørgrav else 1710daf62d9SStanislav Sedov procstat = procstat_open_sysctl(); 1720daf62d9SStanislav Sedov if (procstat == NULL) 1730daf62d9SStanislav Sedov errx(1, "procstat_open()"); 1740daf62d9SStanislav Sedov p = procstat_getprocs(procstat, what, arg, &cnt); 1750daf62d9SStanislav Sedov if (p == NULL) 1760daf62d9SStanislav Sedov errx(1, "procstat_getprocs()"); 1771f910d6cSDag-Erling Smørgrav 1780daf62d9SStanislav Sedov /* 1790daf62d9SStanislav Sedov * Print header. 1800daf62d9SStanislav Sedov */ 1811f910d6cSDag-Erling Smørgrav if (nflg) 1821f910d6cSDag-Erling Smørgrav printf("%s", 1831f910d6cSDag-Erling Smørgrav "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); 1841f910d6cSDag-Erling Smørgrav else 1851f910d6cSDag-Erling Smørgrav printf("%s", 1861f910d6cSDag-Erling Smørgrav "USER CMD PID FD MOUNT INUM MODE SZ|DV R/W"); 1871f910d6cSDag-Erling Smørgrav if (checkfile && fsflg == 0) 1881f910d6cSDag-Erling Smørgrav printf(" NAME\n"); 1891f910d6cSDag-Erling Smørgrav else 1901f910d6cSDag-Erling Smørgrav putchar('\n'); 1910daf62d9SStanislav Sedov 1920daf62d9SStanislav Sedov /* 1930daf62d9SStanislav Sedov * Go through the process list. 1940daf62d9SStanislav Sedov */ 1950daf62d9SStanislav Sedov for (i = 0; i < cnt; i++) { 1960daf62d9SStanislav Sedov if (p[i].ki_stat == SZOMB) 1970daf62d9SStanislav Sedov continue; 1980daf62d9SStanislav Sedov dofiles(procstat, &p[i]); 1990daf62d9SStanislav Sedov } 2000daf62d9SStanislav Sedov procstat_freeprocs(procstat, p); 2010daf62d9SStanislav Sedov procstat_close(procstat); 2020daf62d9SStanislav Sedov return (0); 2031f910d6cSDag-Erling Smørgrav } 2041f910d6cSDag-Erling Smørgrav 2051f910d6cSDag-Erling Smørgrav static void 2060daf62d9SStanislav Sedov dofiles(struct procstat *procstat, struct kinfo_proc *kp) 2071f910d6cSDag-Erling Smørgrav { 2080daf62d9SStanislav Sedov const char *cmd; 2090daf62d9SStanislav Sedov const char *uname; 2100daf62d9SStanislav Sedov struct filestat *fst; 2110daf62d9SStanislav Sedov struct filestat_list *head; 2120daf62d9SStanislav Sedov int pid; 2131f910d6cSDag-Erling Smørgrav 2140daf62d9SStanislav Sedov uname = user_from_uid(kp->ki_uid, 0); 2150daf62d9SStanislav Sedov pid = kp->ki_pid; 2160daf62d9SStanislav Sedov cmd = kp->ki_comm; 2171f910d6cSDag-Erling Smørgrav 2180daf62d9SStanislav Sedov head = procstat_getfiles(procstat, kp, mflg); 2190daf62d9SStanislav Sedov if (head == NULL) 2200daf62d9SStanislav Sedov return; 2210daf62d9SStanislav Sedov STAILQ_FOREACH(fst, head, next) 2220daf62d9SStanislav Sedov print_file_info(procstat, fst, uname, cmd, pid); 2230daf62d9SStanislav Sedov procstat_freefiles(procstat, head); 2249b50d902SRodney W. Grimes } 2250daf62d9SStanislav Sedov 2261f910d6cSDag-Erling Smørgrav 2271f910d6cSDag-Erling Smørgrav static void 2280daf62d9SStanislav Sedov print_file_info(struct procstat *procstat, struct filestat *fst, 2290daf62d9SStanislav Sedov const char *uname, const char *cmd, int pid) 2301f910d6cSDag-Erling Smørgrav { 2310daf62d9SStanislav Sedov struct vnstat vn; 23227d57ea9SDavid Malone DEVS *d; 2330daf62d9SStanislav Sedov const char *filename; 2340daf62d9SStanislav Sedov int error, fsmatch = 0; 2350daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 2369b50d902SRodney W. Grimes 2370daf62d9SStanislav Sedov filename = NULL; 2380daf62d9SStanislav Sedov if (checkfile != 0) { 239b4fe201cSSergey Kandaurov if (fst->fs_type != PS_FST_TYPE_VNODE && 240b4fe201cSSergey Kandaurov fst->fs_type != PS_FST_TYPE_FIFO) 241e22c40faSSergey Kandaurov return; 242b4fe201cSSergey Kandaurov error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); 2430daf62d9SStanislav Sedov if (error != 0) 2440daf62d9SStanislav Sedov return; 2450daf62d9SStanislav Sedov 2469b50d902SRodney W. Grimes for (d = devs; d != NULL; d = d->next) 2470daf62d9SStanislav Sedov if (d->fsid == vn.vn_fsid) { 2489b50d902SRodney W. Grimes fsmatch = 1; 249e458cb77SGleb Kurtsou if (d->ino == vn.vn_fileid) { 2509b50d902SRodney W. Grimes filename = d->name; 2519b50d902SRodney W. Grimes break; 2529b50d902SRodney W. Grimes } 2539b50d902SRodney W. Grimes } 2549b50d902SRodney W. Grimes if (fsmatch == 0 || (filename == NULL && fsflg == 0)) 2559b50d902SRodney W. Grimes return; 2569b50d902SRodney W. Grimes } 2579b50d902SRodney W. Grimes 2580daf62d9SStanislav Sedov /* 2590daf62d9SStanislav Sedov * Print entry prefix. 2600daf62d9SStanislav Sedov */ 2610daf62d9SStanislav Sedov printf("%-8.8s %-10s %5d", uname, cmd, pid); 2620daf62d9SStanislav Sedov if (fst->fs_uflags & PS_FST_UFLAG_TEXT) 2630daf62d9SStanislav Sedov printf(" text"); 2640daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) 2650daf62d9SStanislav Sedov printf(" wd"); 2660daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) 2670daf62d9SStanislav Sedov printf(" root"); 2680daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) 2690daf62d9SStanislav Sedov printf(" tr"); 2700daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_MMAP) 2710daf62d9SStanislav Sedov printf(" mmap"); 2720daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) 2730daf62d9SStanislav Sedov printf(" jail"); 2740daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_CTTY) 2750daf62d9SStanislav Sedov printf(" ctty"); 2760daf62d9SStanislav Sedov else 2770daf62d9SStanislav Sedov printf(" %4d", fst->fs_fd); 2780daf62d9SStanislav Sedov 2790daf62d9SStanislav Sedov /* 2800daf62d9SStanislav Sedov * Print type-specific data. 2810daf62d9SStanislav Sedov */ 2820daf62d9SStanislav Sedov switch (fst->fs_type) { 2830daf62d9SStanislav Sedov case PS_FST_TYPE_FIFO: 2840daf62d9SStanislav Sedov case PS_FST_TYPE_VNODE: 2850daf62d9SStanislav Sedov print_vnode_info(procstat, fst); 2869b50d902SRodney W. Grimes break; 2870daf62d9SStanislav Sedov case PS_FST_TYPE_SOCKET: 2880daf62d9SStanislav Sedov print_socket_info(procstat, fst); 2890daf62d9SStanislav Sedov break; 2900daf62d9SStanislav Sedov case PS_FST_TYPE_PIPE: 2910daf62d9SStanislav Sedov print_pipe_info(procstat, fst); 2920daf62d9SStanislav Sedov break; 2930daf62d9SStanislav Sedov case PS_FST_TYPE_PTS: 2940daf62d9SStanislav Sedov print_pts_info(procstat, fst); 2950daf62d9SStanislav Sedov break; 296e506e182SJohn Baldwin case PS_FST_TYPE_SHM: 297e506e182SJohn Baldwin print_shm_info(procstat, fst); 298e506e182SJohn Baldwin break; 299958aa575SJohn Baldwin case PS_FST_TYPE_SEM: 300958aa575SJohn Baldwin print_sem_info(procstat, fst); 301958aa575SJohn Baldwin break; 3029b50d902SRodney W. Grimes default: 3030daf62d9SStanislav Sedov if (vflg) 3040daf62d9SStanislav Sedov fprintf(stderr, 3050daf62d9SStanislav Sedov "unknown file type %d for file %d of pid %d\n", 3060daf62d9SStanislav Sedov fst->fs_type, fst->fs_fd, pid); 3079b50d902SRodney W. Grimes } 3089b50d902SRodney W. Grimes if (filename && !fsflg) 3099b50d902SRodney W. Grimes printf(" %s", filename); 3109b50d902SRodney W. Grimes putchar('\n'); 3119b50d902SRodney W. Grimes } 3129b50d902SRodney W. Grimes 3130daf62d9SStanislav Sedov static void 3140daf62d9SStanislav Sedov print_socket_info(struct procstat *procstat, struct filestat *fst) 3159b50d902SRodney W. Grimes { 31627d57ea9SDavid Malone static const char *stypename[] = { 3179b50d902SRodney W. Grimes "unused", /* 0 */ 3189b50d902SRodney W. Grimes "stream", /* 1 */ 3199b50d902SRodney W. Grimes "dgram", /* 2 */ 3209b50d902SRodney W. Grimes "raw", /* 3 */ 3219b50d902SRodney W. Grimes "rdm", /* 4 */ 3229b50d902SRodney W. Grimes "seqpak" /* 5 */ 3239b50d902SRodney W. Grimes }; 3249b50d902SRodney W. Grimes #define STYPEMAX 5 3250daf62d9SStanislav Sedov struct sockstat sock; 3260daf62d9SStanislav Sedov struct protoent *pe; 3270daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 3280daf62d9SStanislav Sedov int error; 3290daf62d9SStanislav Sedov static int isopen; 3309b50d902SRodney W. Grimes 3310daf62d9SStanislav Sedov error = procstat_get_socket_info(procstat, fst, &sock, errbuf); 3320daf62d9SStanislav Sedov if (error != 0) { 3330daf62d9SStanislav Sedov printf("* error"); 3340daf62d9SStanislav Sedov return; 3359b50d902SRodney W. Grimes } 3360daf62d9SStanislav Sedov if (sock.type > STYPEMAX) 3370daf62d9SStanislav Sedov printf("* %s ?%d", sock.dname, sock.type); 3389b50d902SRodney W. Grimes else 3390daf62d9SStanislav Sedov printf("* %s %s", sock.dname, stypename[sock.type]); 3409b50d902SRodney W. Grimes 3419b50d902SRodney W. Grimes /* 3429b50d902SRodney W. Grimes * protocol specific formatting 3439b50d902SRodney W. Grimes * 3449b50d902SRodney W. Grimes * Try to find interesting things to print. For tcp, the interesting 3459b50d902SRodney W. Grimes * thing is the address of the tcpcb, for udp and others, just the 3469b50d902SRodney W. Grimes * inpcb (socket pcb). For unix domain, its the address of the socket 3479b50d902SRodney W. Grimes * pcb and the address of the connected pcb (if connected). Otherwise 3489b50d902SRodney W. Grimes * just print the protocol number and address of the socket itself. 3499b50d902SRodney W. Grimes * The idea is not to duplicate netstat, but to make available enough 3509b50d902SRodney W. Grimes * information for further analysis. 3519b50d902SRodney W. Grimes */ 3520daf62d9SStanislav Sedov switch (sock.dom_family) { 3539b50d902SRodney W. Grimes case AF_INET: 354677e00c0SYoshinobu Inoue case AF_INET6: 3550daf62d9SStanislav Sedov if (!isopen) 3560daf62d9SStanislav Sedov setprotoent(++isopen); 3570daf62d9SStanislav Sedov if ((pe = getprotobynumber(sock.proto)) != NULL) 3580daf62d9SStanislav Sedov printf(" %s", pe->p_name); 3590daf62d9SStanislav Sedov else 3600daf62d9SStanislav Sedov printf(" %d", sock.proto); 3610daf62d9SStanislav Sedov if (sock.proto == IPPROTO_TCP ) { 3620daf62d9SStanislav Sedov if (sock.inp_ppcb != 0) 3630daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.inp_ppcb); 3649b50d902SRodney W. Grimes } 3650daf62d9SStanislav Sedov else if (sock.so_pcb != 0) 3660daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.so_pcb); 3679b50d902SRodney W. Grimes break; 3689b50d902SRodney W. Grimes case AF_UNIX: 3699b50d902SRodney W. Grimes /* print address of pcb and connected pcb */ 3700daf62d9SStanislav Sedov if (sock.so_pcb != 0) { 3710daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.so_pcb); 3720daf62d9SStanislav Sedov if (sock.unp_conn) { 3739b50d902SRodney W. Grimes char shoconn[4], *cp; 3749b50d902SRodney W. Grimes 3759b50d902SRodney W. Grimes cp = shoconn; 3760daf62d9SStanislav Sedov if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE)) 3779b50d902SRodney W. Grimes *cp++ = '<'; 3789b50d902SRodney W. Grimes *cp++ = '-'; 3790daf62d9SStanislav Sedov if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE)) 3809b50d902SRodney W. Grimes *cp++ = '>'; 3819b50d902SRodney W. Grimes *cp = '\0'; 382df94d4d2SMatt Jacob printf(" %s %lx", shoconn, 3830daf62d9SStanislav Sedov (u_long)sock.unp_conn); 3849b50d902SRodney W. Grimes } 3859b50d902SRodney W. Grimes } 3869b50d902SRodney W. Grimes break; 3879b50d902SRodney W. Grimes default: 3889b50d902SRodney W. Grimes /* print protocol number and socket address */ 3890daf62d9SStanislav Sedov printf(" %d %lx", sock.proto, (u_long)sock.so_addr); 3909b50d902SRodney W. Grimes } 3919b50d902SRodney W. Grimes } 3929b50d902SRodney W. Grimes 3930daf62d9SStanislav Sedov static void 3940daf62d9SStanislav Sedov print_pipe_info(struct procstat *procstat, struct filestat *fst) 395bc093719SEd Schouten { 3960daf62d9SStanislav Sedov struct pipestat ps; 3970daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 3980daf62d9SStanislav Sedov int error; 3990daf62d9SStanislav Sedov 4000daf62d9SStanislav Sedov error = procstat_get_pipe_info(procstat, fst, &ps, errbuf); 4010daf62d9SStanislav Sedov if (error != 0) { 4020daf62d9SStanislav Sedov printf("* error"); 4030daf62d9SStanislav Sedov return; 4040daf62d9SStanislav Sedov } 4050daf62d9SStanislav Sedov printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer); 4060daf62d9SStanislav Sedov printf(" %6zd", ps.buffer_cnt); 4070daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 4080daf62d9SStanislav Sedov } 4090daf62d9SStanislav Sedov 4100daf62d9SStanislav Sedov static void 4110daf62d9SStanislav Sedov print_pts_info(struct procstat *procstat, struct filestat *fst) 4120daf62d9SStanislav Sedov { 4130daf62d9SStanislav Sedov struct ptsstat pts; 4140daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 4150daf62d9SStanislav Sedov int error; 4160daf62d9SStanislav Sedov 4170daf62d9SStanislav Sedov error = procstat_get_pts_info(procstat, fst, &pts, errbuf); 4180daf62d9SStanislav Sedov if (error != 0) { 4190daf62d9SStanislav Sedov printf("* error"); 4200daf62d9SStanislav Sedov return; 4210daf62d9SStanislav Sedov } 4220daf62d9SStanislav Sedov printf("* pseudo-terminal master "); 4230daf62d9SStanislav Sedov if (nflg || !*pts.devname) { 4249f365aa1SEd Schouten printf("%#10jx", (uintmax_t)pts.dev); 4250daf62d9SStanislav Sedov } else { 4260daf62d9SStanislav Sedov printf("%10s", pts.devname); 4270daf62d9SStanislav Sedov } 4280daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 4290daf62d9SStanislav Sedov } 4300daf62d9SStanislav Sedov 4310daf62d9SStanislav Sedov static void 432958aa575SJohn Baldwin print_sem_info(struct procstat *procstat, struct filestat *fst) 433958aa575SJohn Baldwin { 434958aa575SJohn Baldwin struct semstat sem; 435958aa575SJohn Baldwin char errbuf[_POSIX2_LINE_MAX]; 436958aa575SJohn Baldwin char mode[15]; 437958aa575SJohn Baldwin int error; 438958aa575SJohn Baldwin 439958aa575SJohn Baldwin error = procstat_get_sem_info(procstat, fst, &sem, errbuf); 440958aa575SJohn Baldwin if (error != 0) { 441958aa575SJohn Baldwin printf("* error"); 442958aa575SJohn Baldwin return; 443958aa575SJohn Baldwin } 444958aa575SJohn Baldwin if (nflg) { 445958aa575SJohn Baldwin printf(" "); 446958aa575SJohn Baldwin (void)snprintf(mode, sizeof(mode), "%o", sem.mode); 447958aa575SJohn Baldwin } else { 448958aa575SJohn Baldwin printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-"); 449958aa575SJohn Baldwin strmode(sem.mode, mode); 450958aa575SJohn Baldwin } 451958aa575SJohn Baldwin printf(" %10s %6u", mode, sem.value); 452958aa575SJohn Baldwin print_access_flags(fst->fs_fflags); 453958aa575SJohn Baldwin } 454958aa575SJohn Baldwin 455958aa575SJohn Baldwin static void 456e506e182SJohn Baldwin print_shm_info(struct procstat *procstat, struct filestat *fst) 457e506e182SJohn Baldwin { 458e506e182SJohn Baldwin struct shmstat shm; 459e506e182SJohn Baldwin char errbuf[_POSIX2_LINE_MAX]; 460e506e182SJohn Baldwin char mode[15]; 461e506e182SJohn Baldwin int error; 462e506e182SJohn Baldwin 463e506e182SJohn Baldwin error = procstat_get_shm_info(procstat, fst, &shm, errbuf); 464e506e182SJohn Baldwin if (error != 0) { 465e506e182SJohn Baldwin printf("* error"); 466e506e182SJohn Baldwin return; 467e506e182SJohn Baldwin } 468e506e182SJohn Baldwin if (nflg) { 469e506e182SJohn Baldwin printf(" "); 470e506e182SJohn Baldwin (void)snprintf(mode, sizeof(mode), "%o", shm.mode); 471e506e182SJohn Baldwin } else { 472e506e182SJohn Baldwin printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-"); 473e506e182SJohn Baldwin strmode(shm.mode, mode); 474e506e182SJohn Baldwin } 475e506e182SJohn Baldwin printf(" %10s %6ju", mode, shm.size); 476e506e182SJohn Baldwin print_access_flags(fst->fs_fflags); 477e506e182SJohn Baldwin } 478e506e182SJohn Baldwin 479e506e182SJohn Baldwin static void 4800daf62d9SStanislav Sedov print_vnode_info(struct procstat *procstat, struct filestat *fst) 4810daf62d9SStanislav Sedov { 4820daf62d9SStanislav Sedov struct vnstat vn; 4830daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 4840daf62d9SStanislav Sedov char mode[15]; 4850daf62d9SStanislav Sedov const char *badtype; 4860daf62d9SStanislav Sedov int error; 4870daf62d9SStanislav Sedov 4880daf62d9SStanislav Sedov badtype = NULL; 4890daf62d9SStanislav Sedov error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); 4900daf62d9SStanislav Sedov if (error != 0) 4910daf62d9SStanislav Sedov badtype = errbuf; 4920daf62d9SStanislav Sedov else if (vn.vn_type == PS_FST_VTYPE_VBAD) 4930daf62d9SStanislav Sedov badtype = "bad"; 4940daf62d9SStanislav Sedov else if (vn.vn_type == PS_FST_VTYPE_VNON) 4950daf62d9SStanislav Sedov badtype = "none"; 4960daf62d9SStanislav Sedov if (badtype != NULL) { 4970daf62d9SStanislav Sedov printf(" - - %10s -", badtype); 4980daf62d9SStanislav Sedov return; 4990daf62d9SStanislav Sedov } 5000daf62d9SStanislav Sedov 5010daf62d9SStanislav Sedov if (nflg) 50205806a06SEd Schouten printf(" %#5jx", (uintmax_t)vn.vn_fsid); 5030daf62d9SStanislav Sedov else if (vn.vn_mntdir != NULL) 5040daf62d9SStanislav Sedov (void)printf(" %-8s", vn.vn_mntdir); 5050daf62d9SStanislav Sedov 5060daf62d9SStanislav Sedov /* 5070daf62d9SStanislav Sedov * Print access mode. 5080daf62d9SStanislav Sedov */ 5090daf62d9SStanislav Sedov if (nflg) 5100daf62d9SStanislav Sedov (void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode); 5110daf62d9SStanislav Sedov else { 5120daf62d9SStanislav Sedov strmode(vn.vn_mode, mode); 5130daf62d9SStanislav Sedov } 51476db9ccfSWarner Losh (void)printf(" %6jd %10s", (intmax_t)vn.vn_fileid, mode); 5150daf62d9SStanislav Sedov 5160daf62d9SStanislav Sedov if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) { 5170daf62d9SStanislav Sedov if (nflg || !*vn.vn_devname) 5189f365aa1SEd Schouten printf(" %#6jx", (uintmax_t)vn.vn_dev); 5190daf62d9SStanislav Sedov else { 5200daf62d9SStanislav Sedov printf(" %6s", vn.vn_devname); 5210daf62d9SStanislav Sedov } 5220daf62d9SStanislav Sedov } else 5238d917b4bSWarner Losh printf(" %6ju", (uintmax_t)vn.vn_size); 5240daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 5250daf62d9SStanislav Sedov } 5260daf62d9SStanislav Sedov 5270daf62d9SStanislav Sedov static void 5280daf62d9SStanislav Sedov print_access_flags(int flags) 5290daf62d9SStanislav Sedov { 530bc093719SEd Schouten char rw[3]; 531bc093719SEd Schouten 532bc093719SEd Schouten rw[0] = '\0'; 5330daf62d9SStanislav Sedov if (flags & PS_FST_FFLAG_READ) 534bc093719SEd Schouten strcat(rw, "r"); 5350daf62d9SStanislav Sedov if (flags & PS_FST_FFLAG_WRITE) 536bc093719SEd Schouten strcat(rw, "w"); 5370daf62d9SStanislav Sedov printf(" %2s", rw); 5389b50d902SRodney W. Grimes } 5399b50d902SRodney W. Grimes 5401c17fc99SPeter Wemm int 5411e925017SDavid Malone getfname(const char *filename) 5429b50d902SRodney W. Grimes { 5439b50d902SRodney W. Grimes struct stat statbuf; 5449b50d902SRodney W. Grimes DEVS *cur; 5459b50d902SRodney W. Grimes 5469b50d902SRodney W. Grimes if (stat(filename, &statbuf)) { 547c1e65942SPhilippe Charnier warn("%s", filename); 5489b50d902SRodney W. Grimes return (0); 5499b50d902SRodney W. Grimes } 550c1e65942SPhilippe Charnier if ((cur = malloc(sizeof(DEVS))) == NULL) 551c1e65942SPhilippe Charnier err(1, NULL); 5529b50d902SRodney W. Grimes cur->next = devs; 5539b50d902SRodney W. Grimes devs = cur; 5549b50d902SRodney W. Grimes 5559b50d902SRodney W. Grimes cur->ino = statbuf.st_ino; 556b628b0dcSDavid Malone cur->fsid = statbuf.st_dev; 5579b50d902SRodney W. Grimes cur->name = filename; 5589b50d902SRodney W. Grimes return (1); 5599b50d902SRodney W. Grimes } 5609b50d902SRodney W. Grimes 5610daf62d9SStanislav Sedov static void 5621e925017SDavid Malone usage(void) 5639b50d902SRodney W. Grimes { 5649b50d902SRodney W. Grimes (void)fprintf(stderr, 565f682f10cSRuslan Ermilov "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [file ...]\n"); 5669b50d902SRodney W. Grimes exit(1); 5679b50d902SRodney W. Grimes } 568