1 /* $NetBSD: fstat.c,v 1.120 2023/11/02 10:31:55 martin Exp $ */
2
3 /*-
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
35 The Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
37
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95";
41 #else
42 __RCSID("$NetBSD: fstat.c,v 1.120 2023/11/02 10:31:55 martin Exp $");
43 #endif
44 #endif /* not lint */
45
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/time.h>
49 #include <sys/proc.h>
50 #include <sys/stat.h>
51 #include <sys/vnode.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/unpcb.h>
57 #include <sys/sysctl.h>
58 #include <sys/filedesc.h>
59 #include <sys/pipe.h>
60 #define _KERNEL
61 #include <sys/mount.h>
62 #undef _KERNEL
63 #define _KERNEL
64 #include <sys/file.h>
65 #include <ufs/ufs/inode.h>
66 #include <ufs/ufs/ufsmount.h>
67 #undef _KERNEL
68 #define NFS
69 #include <nfs/nfsproto.h>
70 #include <nfs/rpcv2.h>
71 #include <nfs/nfs.h>
72 #include <nfs/nfsnode.h>
73 #undef NFS
74 #include <msdosfs/denode.h>
75 #include <msdosfs/bpb.h>
76 #define _KERNEL
77 #include <msdosfs/msdosfsmount.h>
78 #undef _KERNEL
79 #define _KERNEL
80 #include <miscfs/genfs/layer.h>
81 #undef _KERNEL
82
83 #include <net/route.h>
84 #include <netinet/in.h>
85 #include <netinet/in_systm.h>
86 #include <netinet/ip.h>
87 #include <netinet/in_pcb.h>
88
89 #ifdef INET6
90 #include <netinet/ip6.h>
91 #include <netinet6/in6.h>
92 #include <netinet6/ip6_var.h>
93 #include <netinet6/in6_pcb.h>
94 #endif
95
96 #include <netatalk/at.h>
97 #include <netatalk/ddp_var.h>
98
99 #include <netdb.h>
100 #include <arpa/inet.h>
101
102 #include <ctype.h>
103 #include <errno.h>
104 #include <kvm.h>
105 #include <limits.h>
106 #include <nlist.h>
107 #include <paths.h>
108 #include <pwd.h>
109 #include <stdio.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <unistd.h>
113 #include <err.h>
114 #include <util.h>
115
116 #include "fstat.h"
117
118 #define TEXT -1
119 #define CDIR -2
120 #define RDIR -3
121 #define TRACE -4
122
123 typedef struct devs {
124 struct devs *next;
125 long fsid;
126 ino_t ino;
127 const char *name;
128 } DEVS;
129 static DEVS *devs;
130
131 static int fsflg, /* show files on same filesystem as file(s) argument */
132 pflg, /* show files open by a particular pid */
133 uflg; /* show files open by a particular (effective) user */
134 static int checkfile; /* true if restricting to particular files or filesystems */
135 static int nflg; /* (numerical) display f.s. and rdev as dev_t */
136 static int Aflg; /* prefix with address of file structure */
137 static int Oflg; /* print offset instead of size */
138 int vflg; /* display errors in locating kernel data objects etc... */
139
140 static fdfile_t **ofiles; /* buffer of pointers to file structures */
141 static int fstat_maxfiles;
142 #define ALLOC_OFILES(d) \
143 if ((d) > fstat_maxfiles) { \
144 size_t len = (d) * sizeof(fdfile_t *); \
145 free(ofiles); \
146 ofiles = malloc(len); \
147 if (ofiles == NULL) { \
148 err(1, "malloc(%zu)", len); \
149 } \
150 fstat_maxfiles = (d); \
151 }
152
153 kvm_t *kd;
154
155 static const char *const dtypes[] = {
156 DTYPE_NAMES
157 };
158
159 static void dofiles(struct kinfo_proc2 *);
160 static int ext2fs_filestat(struct vnode *, struct filestat *);
161 static int getfname(const char *);
162 static void getinetproto(char *, size_t, int);
163 static void getatproto(char *, size_t, int);
164 static char *getmnton(struct mount *);
165 static const char *layer_filestat(struct vnode *, struct filestat *);
166 static int msdosfs_filestat(struct vnode *, struct filestat *);
167 static int nfs_filestat(struct vnode *, struct filestat *);
168 static const char *inet_addrstr(char *, size_t, const struct in_addr *,
169 uint16_t, bool);
170 #ifdef INET6
171 static const char *inet6_addrstr(char *, size_t, const struct in6_addr *,
172 uint16_t, bool);
173 #endif
174 static const char *at_addrstr(char *, size_t, const struct sockaddr_at *);
175 static void socktrans(struct file *, struct socket *, int);
176 static void misctrans(struct file *, int);
177 static int ufs_filestat(struct vnode *, struct filestat *);
178 static void usage(void) __dead;
179 static const char *vfilestat(struct vnode *, struct filestat *);
180 static void vtrans(struct file *, struct vnode *, int, int, long);
181 static void ftrans(fdfile_t *, int);
182 static void ptrans(struct file *, struct pipe *, int);
183 static void kdriver_init(void);
184 static void check_privs(void);
185
186 int
main(int argc,char ** argv)187 main(int argc, char **argv)
188 {
189 struct passwd *passwd;
190 struct kinfo_proc2 *p, *plast;
191 int arg, ch, what;
192 char *memf, *nlistf;
193 char buf[_POSIX2_LINE_MAX];
194 int cnt;
195 gid_t egid = getegid();
196
197 (void)setegid(getgid());
198 arg = 0;
199 what = KERN_PROC_ALL;
200 nlistf = memf = NULL;
201 while ((ch = getopt(argc, argv, "fnAOp:u:vN:M:")) != -1)
202 switch((char)ch) {
203 case 'f':
204 fsflg = 1;
205 break;
206 case 'M':
207 memf = optarg;
208 break;
209 case 'N':
210 nlistf = optarg;
211 break;
212 case 'n':
213 nflg = 1;
214 break;
215 case 'A':
216 Aflg = 1;
217 break;
218 case 'O':
219 Oflg = 1;
220 break;
221 case 'p':
222 if (pflg++)
223 usage();
224 if (!isdigit((unsigned char)*optarg)) {
225 warnx("-p requires a process id");
226 usage();
227 }
228 what = KERN_PROC_PID;
229 arg = atoi(optarg);
230 break;
231 case 'u':
232 if (uflg++)
233 usage();
234 if (!(passwd = getpwnam(optarg))) {
235 errx(1, "%s: unknown uid", optarg);
236 }
237 what = KERN_PROC_UID;
238 arg = passwd->pw_uid;
239 break;
240 case 'v':
241 vflg = 1;
242 break;
243 case '?':
244 default:
245 usage();
246 }
247
248 check_privs();
249
250 kdriver_init();
251
252 if (*(argv += optind)) {
253 for (; *argv; ++argv) {
254 if (getfname(*argv))
255 checkfile = 1;
256 }
257 if (!checkfile) /* file(s) specified, but none accessible */
258 exit(1);
259 }
260
261 ALLOC_OFILES(256); /* reserve space for file pointers */
262
263 if (fsflg && !checkfile) {
264 /* -f with no files means use wd */
265 if (getfname(".") == 0)
266 exit(1);
267 checkfile = 1;
268 }
269
270 /*
271 * Discard setgid privileges. If not the running kernel, we toss
272 * them away totally so that bad guys can't print interesting stuff
273 * from kernel memory, otherwise switch back to kmem for the
274 * duration of the kvm_openfiles() call.
275 */
276 if (nlistf != NULL || memf != NULL)
277 (void)setgid(getgid());
278 else
279 (void)setegid(egid);
280
281 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL)
282 errx(1, "%s", buf);
283
284 /* get rid of it now anyway */
285 if (nlistf == NULL && memf == NULL)
286 (void)setgid(getgid());
287
288 if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) {
289 errx(1, "%s", kvm_geterr(kd));
290 }
291 if (Aflg)
292 (void)printf("%-*s ", 2*(int)(sizeof(void*)), "ADDR");
293 if (nflg)
294 (void)printf(
295 "USER CMD PID FD DEV INUM MODE %s R/W",
296 Oflg ? " OFFS" : "SZ|DV" );
297 else
298 (void)printf(
299 "USER CMD PID FD MOUNT INUM MODE %s R/W",
300 Oflg ? " OFFS" : "SZ|DV" );
301
302 if (checkfile && fsflg == 0)
303 (void)printf(" NAME\n");
304 else
305 (void)putchar('\n');
306
307 for (plast = &p[cnt]; p < plast; ++p) {
308 if (p->p_stat == SZOMB)
309 continue;
310 dofiles(p);
311 }
312 return 0;
313 }
314
315 static void
check_privs(void)316 check_privs(void)
317 {
318 int expaddr;
319 size_t expsize = sizeof(expaddr);
320 const char *expname = "kern.expose_address";
321
322 if (geteuid() == 0)
323 return;
324
325 if (sysctlbyname(expname, &expaddr, &expsize, NULL, 0) == -1)
326 err(EXIT_FAILURE, "Can't get sysctl `%s'", expname);
327 if (expaddr == 0)
328 errx(EXIT_FAILURE, "This program does not work without "
329 "sysctl `%s' being set", expname);
330 }
331
332 static const char *Uname, *Comm;
333 pid_t Pid;
334
335 #define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
336 switch(i) { \
337 case TEXT: \
338 (void)printf(" text"); \
339 break; \
340 case CDIR: \
341 (void)printf(" wd"); \
342 break; \
343 case RDIR: \
344 (void)printf(" root"); \
345 break; \
346 case TRACE: \
347 (void)printf(" tr"); \
348 break; \
349 default: \
350 (void)printf(" %4d", i); \
351 break; \
352 }
353
354 static struct kinfo_drivers *kdriver;
355 static size_t kdriverlen;
356
357 static int
kdriver_comp(const void * a,const void * b)358 kdriver_comp(const void *a, const void *b)
359 {
360 const struct kinfo_drivers *ka = a;
361 const struct kinfo_drivers *kb = b;
362 int kac = ka->d_cmajor == -1 ? 0 : ka->d_cmajor;
363 int kbc = kb->d_cmajor == -1 ? 0 : kb->d_cmajor;
364 int kab = ka->d_bmajor == -1 ? 0 : ka->d_bmajor;
365 int kbb = kb->d_bmajor == -1 ? 0 : kb->d_bmajor;
366 int c = kac - kbc;
367 if (c == 0)
368 return kab - kbb;
369 else
370 return c;
371 }
372
373 static const char *
kdriver_search(int type,dev_t num)374 kdriver_search(int type, dev_t num)
375 {
376 struct kinfo_drivers k, *kp;
377 static char buf[64];
378
379 if (nflg)
380 goto out;
381
382 if (type == VBLK) {
383 k.d_bmajor = num;
384 k.d_cmajor = -1;
385 } else {
386 k.d_bmajor = -1;
387 k.d_cmajor = num;
388 }
389 kp = bsearch(&k, kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp);
390 if (kp)
391 return kp->d_name;
392 out:
393 snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num);
394 return buf;
395 }
396
397
398 static void
kdriver_init(void)399 kdriver_init(void)
400 {
401 size_t sz;
402 int error;
403 static const int name[2] = { CTL_KERN, KERN_DRIVERS };
404
405 error = sysctl(name, __arraycount(name), NULL, &sz, NULL, 0);
406 if (error == -1) {
407 warn("sysctl kern.drivers");
408 return;
409 }
410
411 if (sz % sizeof(*kdriver)) {
412 warnx("bad size %zu for kern.drivers", sz);
413 return;
414 }
415
416 kdriver = malloc(sz);
417 if (kdriver == NULL) {
418 warn("malloc");
419 return;
420 }
421
422 error = sysctl(name, __arraycount(name), kdriver, &sz, NULL, 0);
423 if (error == -1) {
424 warn("sysctl kern.drivers");
425 return;
426 }
427
428 kdriverlen = sz / sizeof(*kdriver);
429 qsort(kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp);
430 #ifdef DEBUG
431 for (size_t i = 0; i < kdriverlen; i++)
432 printf("%d %d %s\n", kdriver[i].d_cmajor, kdriver[i].d_bmajor,
433 kdriver[i].d_name);
434 #endif
435 }
436
437 /*
438 * print open files attributed to this process
439 */
440 static void
dofiles(struct kinfo_proc2 * p)441 dofiles(struct kinfo_proc2 *p)
442 {
443 int i;
444 struct filedesc filed;
445 struct cwdinfo cwdi;
446 struct fdtab dt;
447
448 Uname = user_from_uid(p->p_uid, 0);
449 Pid = p->p_pid;
450 Comm = p->p_comm;
451
452 if (p->p_fd == 0 || p->p_cwdi == 0)
453 return;
454 if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) {
455 warnx("can't read filedesc at %p for pid %d",
456 (void *)(uintptr_t)p->p_fd, Pid);
457 return;
458 }
459 if (filed.fd_lastfile == -1)
460 return;
461 if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) {
462 warnx("can't read cwdinfo at %p for pid %d",
463 (void *)(uintptr_t)p->p_cwdi, Pid);
464 return;
465 }
466 if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) {
467 warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid);
468 return;
469 }
470 if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles ||
471 filed.fd_freefile > filed.fd_lastfile + 1) {
472 dprintf("filedesc corrupted at %p for pid %d",
473 (void *)(uintptr_t)p->p_fd, Pid);
474 return;
475 }
476 /*
477 * root directory vnode, if one
478 */
479 if (cwdi.cwdi_rdir)
480 vtrans(NULL, cwdi.cwdi_rdir, RDIR, FREAD, (long)cwdi.cwdi_rdir);
481 /*
482 * current working directory vnode
483 */
484 vtrans(NULL, cwdi.cwdi_cdir, CDIR, FREAD, (long)cwdi.cwdi_cdir);
485 #if 0
486 /*
487 * Disable for now, since p->p_tracep appears to point to a ktr_desc *
488 * ktrace vnode, if one
489 */
490 if (p->p_tracep)
491 ftrans(p->p_tracep, TRACE);
492 #endif
493 /*
494 * open files
495 */
496 #define FPSIZE (sizeof (fdfile_t *))
497 ALLOC_OFILES(filed.fd_lastfile+1);
498 if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles,
499 (filed.fd_lastfile+1) * FPSIZE)) {
500 dprintf("can't read file structures at %p for pid %d",
501 &filed.fd_dt->dt_ff, Pid);
502 return;
503 }
504 for (i = 0; i <= filed.fd_lastfile; i++) {
505 if (ofiles[i] == NULL)
506 continue;
507 ftrans(ofiles[i], i);
508 }
509 }
510
511 static void
ftrans(fdfile_t * fp,int i)512 ftrans(fdfile_t *fp, int i)
513 {
514 struct file file;
515 fdfile_t fdfile;
516
517 if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) {
518 dprintf("can't read file %d at %p for pid %d",
519 i, fp, Pid);
520 return;
521 }
522 if (fdfile.ff_file == NULL) {
523 dprintf("null ff_file for %d at %p for pid %d",
524 i, fp, Pid);
525 return;
526 }
527 if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) {
528 dprintf("can't read file %d at %p for pid %d",
529 i, fdfile.ff_file, Pid);
530 return;
531 }
532 if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0)
533 (void)printf("%*lx ",
534 2*(int)(sizeof(void*)), (long)fdfile.ff_file);
535 switch (file.f_type) {
536 case DTYPE_VNODE:
537 vtrans(&file, file.f_data, i, file.f_flag, (long)fdfile.ff_file);
538 break;
539 case DTYPE_SOCKET:
540 socktrans(&file, file.f_data, i);
541 break;
542 case DTYPE_PIPE:
543 if (checkfile == 0)
544 ptrans(&file, file.f_data, i);
545 break;
546 case DTYPE_MISC:
547 case DTYPE_KQUEUE:
548 case DTYPE_CRYPTO:
549 case DTYPE_MQUEUE:
550 case DTYPE_SEM:
551 case DTYPE_MEMFD:
552 if (checkfile == 0)
553 misctrans(&file, i);
554 break;
555 default:
556 dprintf("unknown file type %d for file %d of pid %d",
557 file.f_type, i, Pid);
558 break;
559 }
560 }
561
562 static const char dead[] = "dead";
563 static const char *vnode_tag[] = {
564 VNODE_TAGS
565 };
566
567 static const char *
vfilestat(struct vnode * vp,struct filestat * fsp)568 vfilestat(struct vnode *vp, struct filestat *fsp)
569 {
570 const char *badtype = NULL;
571
572 if (vp->v_type == VNON)
573 badtype = "none";
574 else if (vp->v_type == VBAD)
575 badtype = "bad";
576 else
577 switch (vp->v_tag) {
578 case VT_NON:
579 badtype = dead;
580 break;
581 case VT_UFS:
582 case VT_LFS:
583 case VT_MFS:
584 if (!ufs_filestat(vp, fsp))
585 badtype = "error";
586 break;
587 case VT_MSDOSFS:
588 if (!msdosfs_filestat(vp, fsp))
589 badtype = "error";
590 break;
591 case VT_NFS:
592 if (!nfs_filestat(vp, fsp))
593 badtype = "error";
594 break;
595 case VT_EXT2FS:
596 if (!ext2fs_filestat(vp, fsp))
597 badtype = "error";
598 break;
599 case VT_ISOFS:
600 if (!isofs_filestat(vp, fsp))
601 badtype = "error";
602 break;
603 case VT_NTFS:
604 if (!ntfs_filestat(vp, fsp))
605 badtype = "error";
606 break;
607 case VT_PTYFS:
608 if (!ptyfs_filestat(vp, fsp))
609 badtype = "error";
610 break;
611 case VT_TMPFS:
612 if (!tmpfs_filestat(vp, fsp))
613 badtype = "error";
614 break;
615 #ifdef HAVE_ZFS
616 case VT_ZFS:
617 if (!zfs_filestat(vp, fsp))
618 badtype = "error";
619 break;
620 #endif
621 case VT_NULL:
622 case VT_OVERLAY:
623 case VT_UMAP:
624 badtype = layer_filestat(vp, fsp);
625 break;
626 default: {
627 static char unknown[10];
628 (void)snprintf(unknown, sizeof unknown, "%s(%#x)",
629 (size_t)vp->v_tag < __arraycount(vnode_tag) ?
630 vnode_tag[vp->v_tag] : "?", vp->v_tag);
631 badtype = unknown;
632 break;
633 }
634 }
635 return badtype;
636 }
637
638 static int
checkfs(struct vnode * vp,struct vnode * vn,struct filestat * fst,const char ** type,const char ** fname)639 checkfs(struct vnode *vp, struct vnode *vn, struct filestat *fst,
640 const char **type, const char **fname)
641 {
642 *fname = NULL;
643 if (!KVM_READ(vp, vn, sizeof(*vn))) {
644 dprintf("can't read vnode at %p for pid %d", vp, Pid);
645 return 0;
646 }
647 *type = vfilestat(vn, fst);
648 if (checkfile) {
649 int fsmatch = 0;
650 DEVS *d;
651 #if 0
652 if (*type && *type != dead)
653 return 0;
654 #endif
655 for (d = devs; d != NULL; d = d->next) {
656 if (d->fsid == fst->fsid) {
657 fsmatch = 1;
658 if (d->ino == fst->fileid) {
659 *fname = d->name;
660 break;
661 }
662 }
663 }
664 if (fsmatch == 0 || (*fname == NULL && fsflg == 0))
665 return 0;
666 }
667 return 1;
668 }
669
670 static void
vprint(struct vnode * vn,struct filestat * fst)671 vprint(struct vnode *vn, struct filestat *fst)
672 {
673 switch (vn->v_type) {
674 case VBLK:
675 case VCHR: {
676 const char *name;
677
678 if (nflg || ((name = devname(fst->rdev, vn->v_type == VCHR ?
679 S_IFCHR : S_IFBLK)) == NULL))
680 (void)printf(" %s,%-2llu",
681 kdriver_search(vn->v_type, major(fst->rdev)),
682 (unsigned long long)minor(fst->rdev));
683 else
684 (void)printf(" %6s", name);
685 break;
686 }
687 default:
688 (void)printf(" %6lld", (long long)fst->size);
689 }
690 }
691
692 void
oprint(struct file * fp,const char * str)693 oprint(struct file *fp, const char *str)
694 {
695 if (Oflg)
696 (void)printf(" %6lld", (long long)(fp ? fp->f_offset : 0));
697 fputs(str, stdout);
698 }
699
700 static void
vtrans(struct file * fp,struct vnode * vp,int i,int flag,long addr)701 vtrans(struct file *fp, struct vnode *vp, int i, int flag, long addr)
702 {
703 struct vnode vn;
704 char mode[15], rw[3];
705 const char *badtype, *filename;
706 struct filestat fst;
707
708 if (!checkfs(vp, &vn, &fst, &badtype, &filename))
709 return;
710
711 if (Aflg)
712 (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr);
713 PREFIX(i);
714 if (badtype == dead) {
715 char buf[1024];
716 (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS,
717 vn.v_iflag | vn.v_vflag | vn.v_uflag);
718 (void)printf(" flags %s\n", buf);
719 return;
720 } else if (badtype) {
721 (void)printf(" - - %10s -\n", badtype);
722 return;
723 }
724 if (nflg)
725 (void)printf(" %3llu,%-2llu",
726 (unsigned long long)major(fst.fsid),
727 (unsigned long long)minor(fst.fsid));
728 else
729 (void)printf(" %-8s", getmnton(vn.v_mount));
730 if (nflg)
731 (void)snprintf(mode, sizeof mode, "%6o", fst.mode);
732 else
733 strmode(fst.mode, mode);
734 (void)printf(" %8"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode);
735 if (Oflg) {
736 oprint(fp, "");
737 } else {
738 vprint(&vn, &fst);
739 }
740 rw[0] = '\0';
741 if (flag & FREAD)
742 (void)strlcat(rw, "r", sizeof(rw));
743 if (flag & FWRITE)
744 (void)strlcat(rw, "w", sizeof(rw));
745 (void)printf(" %-2s", rw);
746 if (filename && !fsflg)
747 (void)printf(" %s", filename);
748 (void)putchar('\n');
749 }
750
751 static int
ufs_filestat(struct vnode * vp,struct filestat * fsp)752 ufs_filestat(struct vnode *vp, struct filestat *fsp)
753 {
754 struct inode inode;
755 struct ufsmount ufsmount;
756 union dinode {
757 struct ufs1_dinode dp1;
758 struct ufs2_dinode dp2;
759 } dip;
760
761 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
762 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid);
763 return 0;
764 }
765
766 if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) {
767 dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid);
768 return 0;
769 }
770
771 switch (ufsmount.um_fstype) {
772 case UFS1:
773 if (!KVM_READ(inode.i_din.ffs1_din, &dip,
774 sizeof(struct ufs1_dinode))) {
775 dprintf("can't read dinode at %p for pid %d",
776 inode.i_din.ffs1_din, Pid);
777 return 0;
778 }
779 fsp->rdev = dip.dp1.di_rdev;
780 break;
781 case UFS2:
782 if (!KVM_READ(inode.i_din.ffs2_din, &dip,
783 sizeof(struct ufs2_dinode))) {
784 dprintf("can't read dinode at %p for pid %d",
785 inode.i_din.ffs2_din, Pid);
786 return 0;
787 }
788 fsp->rdev = dip.dp2.di_rdev;
789 break;
790 default:
791 dprintf("unknown ufs type %ld for pid %d",
792 ufsmount.um_fstype, Pid);
793 break;
794 }
795 fsp->fsid = inode.i_dev & 0xffff;
796 fsp->fileid = inode.i_number;
797 fsp->mode = (mode_t)inode.i_mode;
798 fsp->size = inode.i_size;
799
800 return 1;
801 }
802
803 static int
ext2fs_filestat(struct vnode * vp,struct filestat * fsp)804 ext2fs_filestat(struct vnode *vp, struct filestat *fsp)
805 {
806 struct inode inode;
807 struct ext2fs_dinode dinode;
808
809 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
810 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid);
811 return 0;
812 }
813 fsp->fsid = inode.i_dev & 0xffff;
814 fsp->fileid = inode.i_number;
815
816 if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) {
817 dprintf("can't read ext2fs_dinode at %p for pid %d",
818 inode.i_din.e2fs_din, Pid);
819 return 0;
820 }
821 fsp->mode = dinode.e2di_mode;
822 fsp->size = dinode.e2di_size;
823 fsp->rdev = dinode.e2di_rdev;
824
825 return 1;
826 }
827
828 static int
nfs_filestat(struct vnode * vp,struct filestat * fsp)829 nfs_filestat(struct vnode *vp, struct filestat *fsp)
830 {
831 struct nfsnode nfsnode;
832 struct vattr va;
833
834 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
835 dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp),
836 Pid);
837 return 0;
838 }
839 if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) {
840 dprintf("can't read vnode attributes at %p for pid %d",
841 nfsnode.n_vattr, Pid);
842 return 0;
843 }
844 fsp->fsid = va.va_fsid;
845 fsp->fileid = va.va_fileid;
846 fsp->size = nfsnode.n_size;
847 fsp->rdev = va.va_rdev;
848 fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type);
849
850 return 1;
851 }
852
853 static int
msdosfs_filestat(struct vnode * vp,struct filestat * fsp)854 msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
855 {
856 struct denode de;
857 struct msdosfsmount mp;
858
859 if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) {
860 dprintf("can't read denode at %p for pid %d", VTONFS(vp),
861 Pid);
862 return 0;
863 }
864 if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) {
865 dprintf("can't read mount struct at %p for pid %d", de.de_pmp,
866 Pid);
867 return 0;
868 }
869
870 fsp->fsid = de.de_dev & 0xffff;
871 fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */
872 fsp->size = de.de_FileSize;
873 fsp->rdev = 0; /* msdosfs doesn't support device files */
874 fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type);
875 return 1;
876 }
877
878 static const char *
layer_filestat(struct vnode * vp,struct filestat * fsp)879 layer_filestat(struct vnode *vp, struct filestat *fsp)
880 {
881 struct layer_node layer_node;
882 struct mount mount;
883 struct vnode vn;
884 const char *badtype;
885
886 if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) {
887 dprintf("can't read layer_node at %p for pid %d",
888 VTOLAYER(vp), Pid);
889 return "error";
890 }
891 if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) {
892 dprintf("can't read mount struct at %p for pid %d",
893 vp->v_mount, Pid);
894 return "error";
895 }
896 vp = layer_node.layer_lowervp;
897 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) {
898 dprintf("can't read vnode at %p for pid %d", vp, Pid);
899 return "error";
900 }
901 if ((badtype = vfilestat(&vn, fsp)) == NULL)
902 fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0];
903 return badtype;
904 }
905
906 static char *
getmnton(struct mount * m)907 getmnton(struct mount *m)
908 {
909 static struct mount mount;
910 static struct mtab {
911 struct mtab *next;
912 struct mount *m;
913 char mntonname[MNAMELEN];
914 } *mhead = NULL;
915 struct mtab *mt;
916
917 for (mt = mhead; mt != NULL; mt = mt->next)
918 if (m == mt->m)
919 return mt->mntonname;
920 if (!KVM_READ(m, &mount, sizeof(struct mount))) {
921 warnx("can't read mount table at %p", m);
922 return NULL;
923 }
924 if ((mt = malloc(sizeof (struct mtab))) == NULL) {
925 err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab));
926 }
927 mt->m = m;
928 (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0],
929 MNAMELEN);
930 mt->next = mhead;
931 mhead = mt;
932 return mt->mntonname;
933 }
934
935 static const char *
inet_addrstr(char * buf,size_t len,const struct in_addr * a,uint16_t p,bool isdg)936 inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p, bool isdg)
937 {
938 char addr[256], serv[256];
939 struct sockaddr_in sin;
940 const int niflags =
941 (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) |
942 (isdg ? NI_DGRAM : 0);
943
944
945 (void)memset(&sin, 0, sizeof(sin));
946 sin.sin_family = AF_INET;
947 sin.sin_len = sizeof(sin);
948 sin.sin_addr = *a;
949 sin.sin_port = htons(p);
950
951 serv[0] = '\0';
952
953 if (getnameinfo((struct sockaddr *)&sin, sin.sin_len,
954 addr, sizeof(addr), serv, sizeof(serv), niflags)) {
955 if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL)
956 strlcpy(addr, "invalid", sizeof(addr));
957 }
958
959 if (serv[0] == '\0')
960 snprintf(serv, sizeof(serv), "%u", p);
961
962 if (a->s_addr == INADDR_ANY) {
963 if (p == 0)
964 buf[0] = '\0';
965 else
966 snprintf(buf, len, "*:%s", serv);
967 return buf;
968 }
969
970 snprintf(buf, len, "%s:%s", addr, serv);
971 return buf;
972 }
973
974 #ifdef INET6
975 static const char *
inet6_addrstr(char * buf,size_t len,const struct in6_addr * a,uint16_t p,bool isdg)976 inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p, bool isdg)
977 {
978 char addr[256], serv[256];
979 struct sockaddr_in6 sin6;
980 const int niflags =
981 (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) |
982 (isdg ? NI_DGRAM : 0);
983
984 (void)memset(&sin6, 0, sizeof(sin6));
985 sin6.sin6_family = AF_INET6;
986 sin6.sin6_len = sizeof(sin6);
987 sin6.sin6_addr = *a;
988 sin6.sin6_port = htons(p);
989
990 inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL);
991 serv[0] = '\0';
992
993 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
994 addr, sizeof(addr), serv, sizeof(serv), niflags)) {
995 if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL)
996 strlcpy(addr, "invalid", sizeof(addr));
997 }
998
999 if (serv[0] == '\0')
1000 snprintf(serv, sizeof(serv), "%u", p);
1001
1002 if (IN6_IS_ADDR_UNSPECIFIED(a)) {
1003 if (p == 0)
1004 buf[0] = '\0';
1005 else
1006 snprintf(buf, len, "*:%s", serv);
1007 return buf;
1008 }
1009
1010 if (strchr(addr, ':') == NULL)
1011 snprintf(buf, len, "%s:%s", addr, serv);
1012 else
1013 snprintf(buf, len, "[%s]:%s", addr, serv);
1014
1015 return buf;
1016 }
1017 #endif
1018
1019 static const char *
at_addrstr(char * buf,size_t len,const struct sockaddr_at * sat)1020 at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat)
1021 {
1022 const struct netrange *nr = &sat->sat_range.r_netrange;
1023 const struct at_addr *at = &sat->sat_addr;
1024 char addr[64], phase[64], range[64];
1025
1026 if (sat->sat_port || at->s_net || at->s_node) {
1027 if (at->s_net || at->s_node)
1028 snprintf(addr, sizeof(addr), "%u.%u:%u",
1029 ntohs(at->s_net), at->s_node, sat->sat_port);
1030 else
1031 snprintf(addr, sizeof(addr), "*:%u", sat->sat_port);
1032 } else
1033 addr[0] = '\0';
1034
1035 if (nr->nr_phase)
1036 snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase);
1037 else
1038 phase[0] = '\0';
1039
1040 if (nr->nr_firstnet || nr->nr_lastnet)
1041 snprintf(range, sizeof(range), " range [%u-%u]",
1042 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet));
1043 else
1044 range[0] = '\0';
1045
1046 snprintf(buf, len, "%s%s%s", addr, phase, range);
1047 return buf;
1048 }
1049
1050 static void
socktrans(struct file * f,struct socket * sock,int i)1051 socktrans(struct file *f, struct socket *sock, int i)
1052 {
1053 static const char *stypename[] = {
1054 "unused", /* 0 */
1055 "stream", /* 1 */
1056 "dgram", /* 2 */
1057 "raw", /* 3 */
1058 "rdm", /* 4 */
1059 "seqpak" /* 5 */
1060 };
1061 #define STYPEMAX 5
1062 struct socket so;
1063 struct protosw proto;
1064 struct domain dom;
1065 struct in4pcb in4pcb;
1066 struct in6pcb in6pcb;
1067 struct unpcb unpcb;
1068 struct ddpcb ddpcb;
1069 int len;
1070 char dname[32];
1071 char lbuf[512], fbuf[512], pbuf[24];
1072 bool isdgram;
1073
1074 pbuf[0] = '\0';
1075 /* fill in socket */
1076 if (!KVM_READ(sock, &so, sizeof(struct socket))) {
1077 dprintf("can't read sock at %p", sock);
1078 goto bad;
1079 }
1080
1081 /* fill in protosw entry */
1082 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
1083 dprintf("can't read protosw at %p", so.so_proto);
1084 goto bad;
1085 }
1086
1087 /* fill in domain */
1088 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
1089 dprintf("can't read domain at %p", proto.pr_domain);
1090 goto bad;
1091 }
1092
1093 if (checkfile && dom.dom_family != AF_LOCAL)
1094 return;
1095
1096 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
1097 sizeof(dname) - 1)) != sizeof(dname) -1) {
1098 dprintf("can't read domain name at %p", dom.dom_name);
1099 dname[0] = '\0';
1100 }
1101 else
1102 dname[len] = '\0';
1103
1104 /*
1105 * protocol specific formatting
1106 *
1107 * Try to find interesting things to print. For TCP, the interesting
1108 * thing is the address of the tcpcb, for UDP and others, just the
1109 * inpcb (socket pcb). For UNIX domain, its the address of the socket
1110 * pcb and the address of the connected pcb (if connected). Otherwise
1111 * just print the protocol number and address of the socket itself.
1112 * The idea is not to duplicate netstat, but to make available enough
1113 * information for further analysis.
1114 */
1115 fbuf[0] = '\0';
1116 lbuf[0] = '\0';
1117 isdgram = false;
1118 switch(dom.dom_family) {
1119 case AF_INET:
1120 getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol);
1121 switch (proto.pr_protocol) {
1122 case IPPROTO_UDP:
1123 isdgram = true;
1124 /* FALLTHROUGH */
1125 case IPPROTO_TCP:
1126 if (so.so_pcb == NULL)
1127 break;
1128 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in4pcb,
1129 sizeof(in4pcb)) != sizeof(in4pcb)) {
1130 dprintf("can't read in4pcb at %p", so.so_pcb);
1131 goto bad;
1132 }
1133 struct inpcb *inp = (struct inpcb *)&in4pcb;
1134 inet_addrstr(lbuf, sizeof(lbuf), &in4p_laddr(inp),
1135 ntohs(inp->inp_lport), isdgram);
1136 inet_addrstr(fbuf, sizeof(fbuf), &in4p_faddr(inp),
1137 ntohs(inp->inp_fport), isdgram);
1138 break;
1139 default:
1140 break;
1141 }
1142 break;
1143 #ifdef INET6
1144 case AF_INET6:
1145 getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol);
1146 switch (proto.pr_protocol) {
1147 case IPPROTO_UDP:
1148 isdgram = true;
1149 /* FALLTHROUGH */
1150 case IPPROTO_TCP:
1151 if (so.so_pcb == NULL)
1152 break;
1153 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb,
1154 sizeof(in6pcb)) != sizeof(in6pcb)) {
1155 dprintf("can't read in6pcb at %p", so.so_pcb);
1156 goto bad;
1157 }
1158 struct inpcb *inp = (struct inpcb *)&in6pcb;
1159 inet6_addrstr(lbuf, sizeof(lbuf), &in6p_laddr(inp),
1160 ntohs(inp->inp_lport), isdgram);
1161 inet6_addrstr(fbuf, sizeof(fbuf), &in6p_faddr(inp),
1162 ntohs(inp->inp_fport), isdgram);
1163 break;
1164 default:
1165 break;
1166 }
1167 break;
1168 #endif
1169 case AF_LOCAL:
1170 /* print address of pcb and connected pcb */
1171 if (so.so_pcb) {
1172 char shoconn[4], *cp;
1173 void *pcb[2];
1174 size_t p = 0;
1175
1176 pcb[0] = so.so_pcb;
1177
1178 cp = shoconn;
1179 if (!(so.so_state & SS_CANTRCVMORE))
1180 *cp++ = '<';
1181 *cp++ = '-';
1182 if (!(so.so_state & SS_CANTSENDMORE))
1183 *cp++ = '>';
1184 *cp = '\0';
1185 again:
1186 if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb,
1187 sizeof(struct unpcb)) != sizeof(struct unpcb)){
1188 dprintf("can't read unpcb at %p", so.so_pcb);
1189 goto bad;
1190 }
1191 if (checkfile) {
1192 struct vnode vn;
1193 struct filestat fst;
1194 const char *badtype, *filename;
1195 if (unpcb.unp_vnode == NULL)
1196 return;
1197 if (!checkfs(unpcb.unp_vnode, &vn, &fst,
1198 &badtype, &filename))
1199 return;
1200 }
1201
1202 if (unpcb.unp_addr) {
1203 struct sockaddr_un *sun =
1204 malloc(unpcb.unp_addrlen);
1205 if (sun == NULL)
1206 err(1, "malloc(%zu)",
1207 unpcb.unp_addrlen);
1208 if (kvm_read(kd, (u_long)unpcb.unp_addr,
1209 sun, unpcb.unp_addrlen) !=
1210 (ssize_t)unpcb.unp_addrlen) {
1211 dprintf("can't read sun at %p",
1212 unpcb.unp_addr);
1213 free(sun);
1214 } else {
1215 snprintf(fbuf, sizeof(fbuf), " %s %s %s",
1216 shoconn, sun->sun_path,
1217 p == 0 ? "[creat]" : "[using]");
1218 free(sun);
1219 break;
1220 }
1221 }
1222 if (unpcb.unp_conn) {
1223 if (p == 0) {
1224 pcb[++p] = unpcb.unp_conn;
1225 goto again;
1226 } else
1227 snprintf(fbuf, sizeof(fbuf),
1228 " %p %s %p", pcb[0], shoconn,
1229 pcb[1]);
1230 }
1231 }
1232 break;
1233 case AF_APPLETALK:
1234 getatproto(pbuf, sizeof(pbuf), proto.pr_protocol);
1235 if (so.so_pcb) {
1236 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb,
1237 sizeof(ddpcb)) != sizeof(ddpcb)){
1238 dprintf("can't read ddpcb at %p", so.so_pcb);
1239 goto bad;
1240 }
1241 at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat);
1242 at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat);
1243 }
1244 break;
1245 default:
1246 /* print protocol number and socket address */
1247 snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol,
1248 (uintmax_t)(uintptr_t)sock);
1249 break;
1250 }
1251 PREFIX(i);
1252 if ((u_short)so.so_type > STYPEMAX)
1253 (void)printf("* %s ?%d", dname, so.so_type);
1254 else
1255 (void)printf("* %s %s", dname, stypename[so.so_type]);
1256
1257 if (pbuf[0])
1258 printf("%s", pbuf);
1259 if (fbuf[0] || lbuf[0])
1260 printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "",
1261 lbuf);
1262 else if (so.so_pcb)
1263 printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb);
1264 oprint(f, "\n");
1265 return;
1266 bad:
1267 (void)printf("* error\n");
1268 }
1269
1270 static void
ptrans(struct file * fp,struct pipe * cpipe,int i)1271 ptrans(struct file *fp, struct pipe *cpipe, int i)
1272 {
1273 struct pipe cp;
1274
1275 PREFIX(i);
1276
1277 /* fill in pipe */
1278 if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) {
1279 dprintf("can't read pipe at %p", cpipe);
1280 goto bad;
1281 }
1282
1283 /* pipe descriptor is either read or write, never both */
1284 (void)printf("* pipe %p %s %p %s%s%s", cpipe,
1285 (fp->f_flag & FWRITE) ? "->" : "<-",
1286 cp.pipe_peer,
1287 (fp->f_flag & FWRITE) ? "w" : "r",
1288 (fp->f_flag & FNONBLOCK) ? "n" : "",
1289 (cp.pipe_state & PIPE_ASYNC) ? "a" : "");
1290 oprint(fp, "\n");
1291 return;
1292 bad:
1293 (void)printf("* error\n");
1294 }
1295
1296 static void
misctrans(struct file * file,int i)1297 misctrans(struct file *file, int i)
1298 {
1299
1300 PREFIX(i);
1301 pmisc(file, dtypes[file->f_type]);
1302 }
1303
1304 /*
1305 * getinetproto --
1306 * print name of protocol number
1307 */
1308 static void
getinetproto(char * buf,size_t len,int number)1309 getinetproto(char *buf, size_t len, int number)
1310 {
1311 const char *cp;
1312
1313 switch (number) {
1314 case IPPROTO_IP:
1315 cp = "ip"; break;
1316 case IPPROTO_ICMP:
1317 cp ="icmp"; break;
1318 case IPPROTO_GGP:
1319 cp ="ggp"; break;
1320 case IPPROTO_TCP:
1321 cp ="tcp"; break;
1322 case IPPROTO_EGP:
1323 cp ="egp"; break;
1324 case IPPROTO_PUP:
1325 cp ="pup"; break;
1326 case IPPROTO_UDP:
1327 cp ="udp"; break;
1328 case IPPROTO_IDP:
1329 cp ="idp"; break;
1330 case IPPROTO_RAW:
1331 cp ="raw"; break;
1332 case IPPROTO_ICMPV6:
1333 cp ="icmp6"; break;
1334 default:
1335 (void)snprintf(buf, len, " %d", number);
1336 return;
1337 }
1338 (void)snprintf(buf, len, " %s", cp);
1339 }
1340
1341 /*
1342 * getatproto --
1343 * print name of protocol number
1344 */
1345 static void
getatproto(char * buf,size_t len,int number)1346 getatproto(char *buf, size_t len, int number)
1347 {
1348 const char *cp;
1349
1350 switch (number) {
1351 case ATPROTO_DDP:
1352 cp = "ddp"; break;
1353 case ATPROTO_AARP:
1354 cp ="aarp"; break;
1355 default:
1356 (void)snprintf(buf, len, " %d", number);
1357 return;
1358 }
1359 (void)snprintf(buf, len, " %s", cp);
1360 }
1361
1362 static int
getfname(const char * filename)1363 getfname(const char *filename)
1364 {
1365 struct stat statbuf;
1366 DEVS *cur;
1367
1368 if (stat(filename, &statbuf)) {
1369 warn("stat(%s)", filename);
1370 return 0;
1371 }
1372 if ((cur = malloc(sizeof(*cur))) == NULL) {
1373 err(1, "malloc(%zu)", sizeof(*cur));
1374 }
1375 cur->next = devs;
1376 devs = cur;
1377
1378 cur->ino = statbuf.st_ino;
1379 cur->fsid = statbuf.st_dev & 0xffff;
1380 cur->name = filename;
1381 return 1;
1382 }
1383
1384 mode_t
getftype(enum vtype v_type)1385 getftype(enum vtype v_type)
1386 {
1387 mode_t ftype;
1388
1389 switch (v_type) {
1390 case VREG:
1391 ftype = S_IFREG;
1392 break;
1393 case VDIR:
1394 ftype = S_IFDIR;
1395 break;
1396 case VBLK:
1397 ftype = S_IFBLK;
1398 break;
1399 case VCHR:
1400 ftype = S_IFCHR;
1401 break;
1402 case VLNK:
1403 ftype = S_IFLNK;
1404 break;
1405 case VSOCK:
1406 ftype = S_IFSOCK;
1407 break;
1408 case VFIFO:
1409 ftype = S_IFIFO;
1410 break;
1411 default:
1412 ftype = 0;
1413 break;
1414 };
1415
1416 return ftype;
1417 }
1418
1419 static void
usage(void)1420 usage(void)
1421 {
1422 (void)fprintf(stderr, "Usage: %s [-Afnv] [-M core] [-N system] "
1423 "[-p pid] [-u user] [file ...]\n", getprogname());
1424 exit(1);
1425 }
1426