1/*
2 * dnode.c - Darwin node functions for /dev/kmem-based lsof
3 */
4
5
6/*
7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907.  All rights reserved.
9 *
10 * Written by Victor A. Abell
11 *
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
14 *
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
18 *
19 * 1. Neither the authors nor Purdue University are responsible for any
20 *    consequences of the use of this software.
21 *
22 * 2. The origin of this software must not be misrepresented, either by
23 *    explicit claim or by omission.  Credit to the authors and Purdue
24 *    University must appear in documentation and sources.
25 *
26 * 3. Altered versions must be plainly marked as such, and must not be
27 *    misrepresented as being the original software.
28 *
29 * 4. This notice may not be removed or altered.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35static char *rcsid = "$Id: dnode.c,v 1.11 2006/03/27 23:24:50 abe Exp $";
36#endif
37
38
39#include "lsof.h"
40
41
42/*
43 * Local function prototypes
44 */
45
46#if	DARWINV<600
47_PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, dev_t *rdr, INODETYPE *ir));
48#endif	/* DARWINV<600 */
49
50#if	DARWINV>=800
51_PROTOTYPE(static char *getvpath,(KA_T va, struct vnode *rv));
52_PROTOTYPE(static int readvname,(KA_T addr, char *buf, int buflen));
53#endif	/* DARWINV>=800 */
54
55
56#if	DARWINV>=800
57/*
58 * getvpath() - get vnode path
59 *		adapted from build_path() (.../bsd/vfs/vfs_subr.c)
60 */
61
62static char *
63getvpath(va, rv)
64	KA_T va;			/* kernel address of the rightmost
65					 * vnode in the path */
66	struct vnode *rv;		/* pointer to rightmost vnode */
67{
68	char *ap;
69	static char *bp = (char *)NULL;
70	static size_t bl = (size_t)(MAXPATHLEN + MAXPATHLEN + 1);
71	static char *cb = (char *)NULL;
72	static size_t cbl = (size_t)0;
73	static int ce = 0;
74	struct mount mb;
75	int pl, vnl;
76	char *pp, vn[MAXPATHLEN+1];
77	struct vnode vb;
78	KA_T vas = va;
79/*
80 * Initialize the path assembly.
81 */
82	if (!bp) {
83	    if (!(bp = (char *)malloc((MALLOC_S)bl))) {
84		(void) fprintf(stderr, "%s: no space (%d) for path assembly\n",
85		    Pn, (int)bl);
86		Exit(1);
87	    }
88	}
89	pp = bp + bl - 1;
90	*pp = '\0';
91	pl = 0;
92/*
93 * Process the starting vnode.
94 */
95	if (!va)
96	    return(0);
97	if ((rv->v_flag & VROOT) && rv->v_mount) {
98
99	/*
100	 * This is the root of a file system and it has a mount structure.
101	 * Read the mount structure.
102	 */
103	    if (kread((KA_T)rv->v_mount, (char *)&mb, sizeof(mb)))
104		return(0);
105	    if (mb.mnt_flag & MNT_ROOTFS) {
106
107	    /*
108	     * This is the root file system, so the path is "/".
109	     */
110		pp--;
111		*pp = '/';
112		pl = 1;
113		goto getvpath_alloc;
114	    } else {
115
116	    /*
117	     * Get the covered vnode's pointer and read it.  Use it to
118	     * form the path.
119	     */
120		if ((va = (KA_T)mb.mnt_vnodecovered)) {
121		    if (readvnode(va, &vb))
122			return(0);
123		}
124	    }
125	} else {
126
127	/*
128	 * Use the supplied vnode.
129	 */
130	    vb = *rv;
131	}
132/*
133 * Accumulate the path from the vnode chain.
134 */
135	while (va && ((KA_T)vb.v_parent != va)) {
136	    if (!vb.v_name) {
137
138	    /*
139	     * If there is no name pointer or parent, the assembly is complete.
140	     */
141		if (vb.v_parent) {
142
143		/*
144		 * It is an error if there is a parent but no name.
145		 */
146		    return((char *)NULL);
147		}
148		break;
149	    }
150	/*
151	 * Read the name and add it to the assembly.
152	 */
153	    if ((vnl = readvname((KA_T)vb.v_name, vn, sizeof(vn))) <= 0)
154		return((char *)NULL);
155	    if ((vnl + 1 + pl + 1) > bl)
156		return((char *)NULL);
157	    memmove((void *)(pp - vnl), (void *)vn, vnl);
158	    pp -= (vnl + 1);
159	    *pp = '/';
160	    pl += vnl + 1;
161	    if ((va == vas) && (vb.v_flag & VROOT)) {
162
163	    /*
164	     * This is the starting vnode and it is a root vnode.  Read its
165	     * mount structure.
166	     */
167		if (vb.v_mount) {
168		    if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
169			return((char *)NULL);
170		    if (mb.mnt_vnodecovered) {
171
172		    /*
173		     * If there's a covered vnode, read it and use it's parent
174		     * vnode pointer.
175		     */
176			if ((va = (KA_T)mb.mnt_vnodecovered)) {
177			    if (readvnode(va, &vb))
178				return((char *)NULL);
179			    va = (KA_T)vb.v_parent;
180			}
181		    } else
182			va = (KA_T)NULL;
183		} else
184		    va = (KA_T)NULL;
185	    } else
186		va = (KA_T)vb.v_parent;
187	/*
188	 * If there's a parent vnode, read it.
189	 */
190	    if (va) {
191		if (readvnode(va, &vb))
192		    return((char *)NULL);
193		if ((vb.v_flag & VROOT) && vb.v_mount) {
194
195		/*
196		 * The mount point has been reached.  Read the mount structure
197		 * and use its covered vnode pointer.
198		 */
199		    if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
200			return((char *)NULL);
201		    if ((va = (KA_T)mb.mnt_vnodecovered)) {
202			if (readvnode(va, &vb))
203			    return((char *)NULL);
204		    }
205		}
206	    }
207	}
208/*
209 * As a special case the following code attempts to trim a path that is
210 * larger than MAXPATHLEN by seeing if the lsof process CWD can be removed
211 * from the start of the path to make it MAXPATHLEN characters or less.
212 */
213	if (pl > MAXPATHLEN) {
214
215	/*
216	 * Get the cwd.  If that can't be done, return an error.
217	 */
218	    if (ce)
219		return((char *)NULL);
220	    if (!cb) {
221		if (!(cb = (char *)malloc((MALLOC_S)(MAXPATHLEN + 1)))) {
222		    (void) fprintf(stderr, "%s: no space (%d) for CWD\n",
223			Pn, (int)bl);
224		    Exit(1);
225		}
226		if (!getcwd(cb, (size_t)(MAXPATHLEN + 1))) {
227		    if (!Fwarn) {
228			(void) fprintf(stderr, "%s: WARNING: can't get CWD\n",
229			    Pn);
230		    }
231		    ce = 1;
232		    return((char *)NULL);
233		}
234		cb[MAXPATHLEN - 1] = '\0';
235		if (!(cbl = (size_t)strlen(cb))) {
236		    if (!Fwarn) {
237			(void) fprintf(stderr, "%s: WARNING: CWD is NULL\n",
238			    Pn);
239		    }
240		    ce = 1;
241		    return((char *)NULL);
242		}
243	    }
244	/*
245	 * See if trimming the CWD shortens the path to MAXPATHLEN or less.
246	 */
247	    if ((pl <= cbl) || strncmp(cb, pp, cbl))
248		return((char *)NULL);
249	    pp += cbl;
250	    pl -= cbl;
251	    if (cb[cbl - 1] == '/') {
252
253	    /*
254	     * The CWD ends in a '/', so the path must not begin with one.  If
255	     * it does, no trimming can be done.
256	     */
257		if (*pp == '/')
258		    return((char *)NULL);
259	    } else {
260
261	    /*
262	     * The CWD doesn't end in a '/', so the path must begin with one.
263	     * If it doesn't, no trimming can be done.
264	     */
265		if (*pp != '/')
266		    return((char *)NULL);
267	    /*
268	     * Skip all leading path '/' characters.  Some characters must
269	     * remain.
270	     */
271		while ((pl > 0) && (*pp == '/')) {
272		    pp++;
273		    pl--;
274		}
275		if (!pl)
276		    return((char *)NULL);
277	    }
278	}
279/*
280 * Allocate space for the assembled path, including terminator, and return its
281 * pointer.
282 */
283
284getvpath_alloc:
285
286	if (!(ap = (char *)malloc(pl + 1))) {
287	    (void) fprintf(stderr, "%s: no getvpath space (%d)\n",
288		Pn, pl + 1);
289	    Exit(1);
290	}
291	(void) memmove(ap, pp, pl + 1);
292	return(ap);
293}
294#endif	/* DARWINV>=800 */
295
296
297#if	DARWINV<600
298/*
299 * lkup_dev_tty() - look up /dev/tty
300 */
301
302static int
303lkup_dev_tty(dr, rdr, ir)
304	dev_t *dr;			/* place to return device number */
305	dev_t *rdr;			/* place to return raw device number */
306	INODETYPE *ir;			/* place to return inode number */
307{
308	int i;
309
310	readdev(0);
311	for (i = 0; i < Ndev; i++) {
312	    if (strcmp(Devtp[i].name, "/dev/tty") == 0) {
313		*dr = DevDev;
314		*rdr = Devtp[i].rdev;
315		*ir = (INODETYPE)Devtp[i].inode;
316		return(1);
317	    }
318	}
319	return(-1);
320}
321#endif	/* DARWINV<600 */
322
323
324/*
325 * process_node() - process vnode
326 */
327
328void
329process_node(va)
330	KA_T va;			/* vnode kernel space address */
331{
332	dev_t dev = (dev_t)0;
333	dev_t rdev = (dev_t)0;
334	unsigned char devs = 0;
335	unsigned char rdevs = 0;
336
337#if	DARWINV<800
338	struct devnode *d = (struct devnode *)NULL;
339	struct devnode db;
340	unsigned char lt;
341	char dev_ch[32];
342
343# if	defined(HASFDESCFS)
344	struct fdescnode *f = (struct fdescnode *)NULL;
345	struct fdescnode fb;
346# endif	/* defined(HASFDESCFS) */
347
348	static INODETYPE fi;
349	static dev_t fdev, frdev;
350	static int fs = 0;
351	struct inode *i = (struct inode *)NULL;
352	struct inode ib;
353	struct lockf lf, *lff, *lfp;
354	struct nfsnode *n = (struct nfsnode *)NULL;
355	struct nfsnode nb;
356#else	/* DARWINV>=800 */
357	struct stat sb;
358	char *vn;
359#endif	/* DARWINV<800 */
360
361	char *ty;
362	enum vtype type;
363	struct vnode *v, vb;
364	struct l_vfs *vfs;
365
366#if	DARWINV<600
367	struct hfsnode *h = (struct hfsnode *)NULL;
368	struct hfsnode hb;
369	struct hfsfilemeta *hm = (struct hfsfilemeta *)NULL;
370	struct hfsfilemeta hmb;
371#else	/* DARWINV>=600 */
372# if	DARWINV<800
373	struct cnode *h = (struct cnode *)NULL;
374	struct cnode hb;
375	struct filefork *hf = (struct filefork *)NULL;
376	struct filefork hfb;
377# endif	/* DARWINV<800 */
378#endif	/* DARWINV<600 */
379
380#if	defined(HAS9660FS)
381	dev_t iso_dev;
382	int iso_dev_def = 0;
383	INODETYPE iso_ino;
384	long iso_links;
385	int iso_stat = 0;
386	SZOFFTYPE iso_sz;
387#endif	/* defined(HAS9660FS) */
388
389/*
390 * Read the vnode.
391 */
392	if ( ! va) {
393	    enter_nm("no vnode address");
394	    return;
395	}
396	v = &vb;
397	if (readvnode(va, v)) {
398	    enter_nm(Namech);
399	    return;
400	}
401	type = v->v_type;
402
403#if	defined(HASNCACHE)
404	Lf->na = va;
405# if	defined(HASNCVPID)
406	Lf->id = v->v_id;
407# endif	/* defined(HASNCVPID) */
408#endif	/* defined(HASNCACHE) */
409
410#if	defined(HASFSTRUCT)
411	Lf->fna = va;
412	Lf->fsv |= FSV_NI;
413#endif	/* defined(HASFSTRUCT) */
414
415/*
416 * Get the vnode type.
417 */
418	if (!v->v_mount)
419	    vfs = (struct l_vfs *)NULL;
420	else {
421	    vfs = readvfs((KA_T)v->v_mount);
422	    if (vfs) {
423		if (strcasecmp(vfs->typnm, "nfs") == 0)
424		    Ntype = N_NFS;
425
426#if	DARWINV<130
427		else if (strcasecmp(vfs->typnm, "afpfs") == 0)
428		    Ntype = N_AFPFS;
429#endif	/* DARWINV<130 */
430
431	    }
432	}
433	if (Ntype == N_REGLR) {
434	    switch (v->v_type) {
435	    case VFIFO:
436		Ntype = N_FIFO;
437		break;
438	    default:
439		break;
440	    }
441	}
442
443#if	DARWINV<800
444/*
445 * Define the specific node pointer.
446 */
447	switch (v->v_tag) {
448
449# if	DARWINV>120
450	case VT_AFP:
451 	    break;
452# endif	/* DARWINV>120 */
453
454# if	DARWINV>120
455	case VT_CDDA:
456	    break;
457# endif	/* DARWINV>120 */
458
459# if	DARWINV>120
460	case VT_CIFS:
461	    break;
462# endif	/* DARWINV>120 */
463
464	case VT_DEVFS:
465	    if (!v->v_data
466	    ||  kread((KA_T)v->v_data, (char *)&db, sizeof(db))) {
467		(void) snpf(Namech, Namechl, "no devfs node: %#x", v->v_data);
468		enter_nm(Namech);
469		return;
470	    }
471	    d = &db;
472	    break;
473
474# if	defined(HASFDESCFS)
475	case VT_FDESC:
476	    if (!v->v_data
477	    ||  kread((KA_T)v->v_data, (char *)&fb, sizeof(fb))) {
478		(void) snpf(Namech, Namechl, "no fdesc node: %s",
479			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
480		enter_nm(Namech);
481		return;
482	    }
483	    f = &fb;
484	    break;
485# endif	/* defined(HASFDESCFS) */
486
487	case VT_HFS:
488
489# if	DARWINV<130
490	    if (Ntype != N_AFPFS) {
491# endif	/* DARWINV<130 */
492
493		if (!v->v_data
494		||  kread((KA_T)v->v_data, (char *)&hb, sizeof(hb))) {
495		    (void) snpf(Namech, Namechl, "no hfs node: %s",
496			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
497		    enter_nm(Namech);
498		    return;
499		}
500		h = &hb;
501
502# if	DARWINV<600
503		if (!h->h_meta
504		||  kread((KA_T)h->h_meta, (char *)&hmb, sizeof(hmb))) {
505		    (void) snpf(Namech, Namechl, "no hfs node metadata: %s",
506			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
507		    enter_nm(Namech);
508		    return;
509		}
510		hm = &hmb;
511# else	/* DARWINV>=600 */
512		if (v->v_type == VDIR)
513		    break;
514		if (h->c_rsrc_vp == v)
515		    hf = h->c_rsrcfork;
516		else
517		    hf = h->c_datafork;
518		if (!hf
519		||  kread((KA_T)hf, (char *)&hfb, sizeof(hfb))) {
520		    (void) snpf(Namech, Namechl, "no hfs node fork: %s",
521			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
522		    enter_nm(Namech);
523		    return;
524		}
525		hf = &hfb;
526# endif	/* DARWINV<600 */
527
528# if	DARWINV<130
529	    }
530# endif	/* DARWINV<130 */
531
532	    break;
533
534# if	defined(HAS9660FS)
535	case VT_ISOFS:
536	    if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links,
537			      &iso_sz))
538	    {
539		(void) snpf(Namech, Namechl, "no iso node: %s",
540			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
541		enter_nm(Namech);
542		return;
543	    }
544	    iso_stat = 1;
545	    break;
546# endif	/* defined(HAS9660FS) */
547
548	case VT_NFS:
549	    if (!v->v_data
550	    ||  kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) {
551		(void) snpf(Namech, Namechl, "no nfs node: %s",
552			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
553		enter_nm(Namech);
554		return;
555	    }
556	    n = &nb;
557	    break;
558
559# if	DARWINV>120
560	case VT_UDF:
561	    break;
562# endif	/* DARWINV>120 */
563
564	case VT_UFS:
565	    if (!v->v_data
566	    ||  kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) {
567		(void) snpf(Namech, Namechl, "no ufs node: %s",
568			print_kptr((KA_T)v->v_data, (char *)NULL, 0));
569		enter_nm(Namech);
570		return;
571	    }
572	    i = &ib;
573	    if ((lff = i->i_lockf)) {
574
575	    /*
576	     * Determine the lock state.
577	     */
578		lfp = lff;
579		do {
580		    if (kread((KA_T)lfp, (char *)&lf, sizeof(lf)))
581			break;
582		    lt = 0;
583		    switch (lf.lf_flags & (F_FLOCK|F_POSIX)) {
584		    case F_FLOCK:
585			if (Cfp && (struct file *)lf.lf_id == Cfp)
586			    lt = 1;
587			break;
588		    case F_POSIX:
589			if ((KA_T)lf.lf_id == Kpa)
590			    lt = 1;
591			break;
592		    }
593		    if (!lt)
594			continue;
595		    if (lf.lf_start == (off_t)0
596		    &&  lf.lf_end == 0xffffffffffffffffLL)
597			lt = 1;
598		    else
599			lt = 0;
600		    if (lf.lf_type == F_RDLCK)
601			Lf->lock = lt ? 'R' : 'r';
602		    else if (lf.lf_type == F_WRLCK)
603			Lf->lock = lt ? 'W' : 'w';
604		    else if (lf.lf_type == (F_RDLCK | F_WRLCK))
605			Lf->lock = 'u';
606		    break;
607		} while ((lfp = lf.lf_next) && lfp != lff);
608	    }
609	    break;
610
611# if	DARWINV>120
612	case VT_WEBDAV:
613   	    break;
614# endif	/* DARWINV>120 */
615
616	default:
617	    if (v->v_type == VBAD || v->v_type == VNON)
618		break;
619	    (void) snpf(Namech, Namechl, "unknown file system type: %d",
620		v->v_tag);
621	    enter_nm(Namech);
622	    return;
623	}
624/*
625 * Get device and type for printing.
626 */
627	if (n) {
628	    dev = n->n_vattr.va_fsid;
629	    devs = 1;
630	} else if (i) {
631	    dev = i->i_dev;
632	    devs = 1;
633	    if ((type == VCHR) || (type == VBLK)) {
634		rdev = i->i_rdev ;
635		rdevs = 1;
636	    }
637	}
638
639# if	defined(HASFDESCFS)
640	else if (f) {
641	    if (f->fd_link
642	    &&  !kread((KA_T)f->fd_link, Namech, Namechl -1))
643		Namech[Namechl - 1] = '\0';
644
645#  if	DARWINV<600
646	    else if (f->fd_type == Fctty) {
647		if (fs == 0)
648		    fs = lkup_dev_tty(&fdev, &frdev, &fi);
649		if (fs == 1) {
650		    dev = fdev;
651		    rdev = frdev;
652		    devs = Lf->inp_ty = rdevs = 1;
653		    Lf->inode = fi;
654		}
655	    }
656	}
657#  endif	/* DARWINV<600 */
658# endif	/* defined(HASFDESCFS) */
659
660	else if (h) {
661
662# if	DARWINV<600
663	    dev = hm->h_dev;
664# else	/* DARWINV>=600 */
665	    dev = h->c_dev;
666# endif	/* DARWINV<600 */
667
668	    devs = 1;
669	    if ((type == VCHR) || (type == VBLK)) {
670
671# if	DARWINV<600
672		rdev = hm->h_rdev;
673# else	/* DARWINV>=600 */
674		rdev = h->c_rdev;
675# endif	/* DARWINV<600 */
676
677		rdevs = 1;
678	    }
679	} else if (d) {
680	    dev = DevDev;
681	    devs = 1;
682	    rdev = d->dn_typeinfo.dev;
683	    rdevs = 1;
684	}
685
686# if	defined(HAS9660FS)
687	else if (iso_stat && iso_dev_def) {
688	    dev = iso_dev;
689	    devs = Lf->inp_ty = 1;
690	}
691# endif	/* defined(HAS9660FS) */
692
693
694/*
695 * Obtain the inode number.
696 */
697	if (i) {
698	    Lf->inode = (INODETYPE)i->i_number;
699	    Lf->inp_ty = 1;
700	} else if (n) {
701	    Lf->inode = (INODETYPE)n->n_vattr.va_fileid;
702	    Lf->inp_ty = 1;
703	} else if (h) {
704
705# if	DARWINV<600
706	    Lf->inode = (INODETYPE)hm->h_nodeID;
707# else	/* DARWINV>=600 */
708	    Lf->inode = (INODETYPE)h->c_fileid;
709# endif	/* DARWINV<600 */
710
711	    Lf->inp_ty = 1;
712	}
713
714# if	defined(HAS9660FS)
715	else if (iso_stat) {
716	    Lf->inode = iso_ino;
717	    Lf->inp_ty = 1;
718	}
719# endif	/* defined(HAS9660FS) */
720
721/*
722 * Obtain the file size.
723 */
724	if (Foffset)
725	    Lf->off_def = 1;
726	else {
727	    switch (Ntype) {
728	    case N_FIFO:
729		if (!Fsize)
730		    Lf->off_def = 1;
731		break;
732	    case N_NFS:
733		if (n) {
734		    Lf->sz = (SZOFFTYPE)n->n_vattr.va_size;
735		    Lf->sz_def = 1;
736		}
737		break;
738
739# if	DARWINV<130
740	    case N_AFPFS:
741		break;
742# endif	/* DARWINV<130 */
743
744	    case N_REGLR:
745		if (type == VREG || type == VDIR) {
746		    if (i) {
747			Lf->sz = (SZOFFTYPE)i->i_size;
748			Lf->sz_def = 1;
749		    } else if (h) {
750
751# if	DARWINV<600
752			Lf->sz = (type == VDIR) ? (SZOFFTYPE)hm->h_size
753						: (SZOFFTYPE)h->fcbEOF;
754# else	/* DARWINV>=600 */
755			if (type == VDIR)
756			    Lf->sz = (SZOFFTYPE)h->c_nlink * 128;
757			else
758			    Lf->sz = (SZOFFTYPE)hf->ff_size;
759# endif	/* DARWINV<600 */
760
761			Lf->sz_def = 1;
762		    }
763
764# if	defined(HAS9660FS)
765		    else if (iso_stat) {
766			Lf->sz = (SZOFFTYPE)iso_sz;
767			Lf->sz_def = 1;
768		    }
769# endif	/* defined(HAS9660FS) */
770
771		}
772		else if ((type == VCHR || type == VBLK) && !Fsize)
773		    Lf->off_def = 1;
774		    break;
775	    }
776	}
777/*
778 * Record the link count.
779 */
780	if (Fnlink) {
781	    switch(Ntype) {
782	    case N_NFS:
783		if (n) {
784		    Lf->nlink = (long)n->n_vattr.va_nlink;
785		    Lf->nlink_def = 1;
786		}
787		break;
788
789# if	DARWINV<130
790	    case N_AFPFS:
791		break;
792# endif	/* DARWINV<130 */
793
794	    case N_REGLR:
795		if (i) {
796		    Lf->nlink = (long)i->i_nlink;
797		    Lf->nlink_def = 1;
798		} else if (h) {
799
800# if	DARWINV<600
801		    Lf->nlink = (long)hm->h_nlink;
802# else	/* DARWINV>=600 */
803		    Lf->nlink = (long)h->c_nlink;
804# endif	/* DARWINV<600 */
805
806		    Lf->nlink_def = 1;
807		}
808
809# if	defined(HAS9660FS)
810		else if (iso_stat) {
811		    Lf->nlink = iso_links;
812		    Lf->nlink_def = 1;
813		}
814# endif	/* defined(HAS9660FS) */
815
816		break;
817	    }
818	    if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
819		Lf->sf |= SELNLINK;
820	}
821#else	/* DARWINV>=800 */
822
823/*
824 * Process a vnode for Darwin >= 8.0.
825 */
826	if ((vn = getvpath(va, v))) {
827
828	/*
829	 * If the vnode yields a path, get the file's information by doing
830	 * a "safe" stat(2) of the path.
831	 */
832	    if (!statsafely(vn, &sb)) {
833
834	    /*
835	     * Save file size or offset.
836	     */
837		if (Foffset) {
838		    Lf->off_def = 1;
839		} else {
840		    switch (Ntype) {
841		    case N_FIFO:
842			if (!Fsize)
843			    Lf->off_def = 1;
844			break;
845		    case N_NFS:
846		    case N_REGLR:
847			if (type == VREG || type == VDIR) {
848			    Lf->sz = sb.st_size;
849			    Lf->sz_def = 1;
850			} else if ((type == VCHR || type == VBLK) && !Fsize)
851			    Lf->off_def = 1;
852			break;
853		    }
854		}
855	    /*
856	     * Save node number.
857	     */
858		Lf->inode = (INODETYPE)sb.st_ino;
859		Lf->inp_ty = 1;
860	    /*
861	     * Optionally save link count.
862	     */
863		if (Fnlink) {
864		    Lf->nlink = sb.st_nlink;
865		    Lf->nlink_def = 1;
866		}
867	    /*
868	     * Save device number and path.
869	     */
870		switch (v->v_tag) {
871		case VT_DEVFS:
872		    if (vn)
873			(void) free((FREE_P *)vn);
874		    dev = DevDev;
875		    devs = 1;
876		    break;
877		default :
878		    Lf->V_path = vn;
879		    dev = sb.st_dev;
880		    devs = 1;
881		    break;
882		}
883	    /*
884	     * Save character and block device number.
885	     */
886		if ((type == VCHR) || (type == VBLK)) {
887		    rdev = sb.st_rdev;
888		    rdevs = 1;
889		}
890	    } else {
891
892	    /*
893	     * Indicate a stat(2) failure in Namech[].
894	     */
895		(void) snpf(Namech, Namechl, "stat(%s): %s", vn,
896		    strerror(errno));
897		(void) free((FREE_P *)vn);
898	    }
899	/*
900	 * Record an NFS file.
901	 */
902	    if (vfs && !strcmp(vfs->typnm, "nfs"))
903		Ntype = N_NFS;
904	}
905#endif	/* DARWINV>=800 */
906
907/*
908 * Record an NFS file selection.
909 */
910	if (Ntype == N_NFS && Fnfs)
911	    Lf->sf |= SELNFS;
912/*
913 * Save the file system names.
914 */
915	if (vfs) {
916	    Lf->fsdir = vfs->dir;
917	    Lf->fsdev = vfs->fsname;
918	}
919/*
920 * Save the device numbers and their states.
921 *
922 * Format the vnode type, and possibly the device name.
923 */
924	Lf->dev = dev;
925	Lf->dev_def = devs;
926	Lf->rdev = rdev;
927	Lf->rdev_def = rdevs;
928	switch (type) {
929	case VNON:
930	    ty ="VNON";
931	    break;
932	case VREG:
933	    ty = "VREG";
934	    break;
935	case VDIR:
936	    ty = "VDIR";
937	    break;
938	case VBLK:
939	    ty = "VBLK";
940	    Ntype = N_BLK;
941	    break;
942	case VCHR:
943	    ty = "VCHR";
944	    Ntype = N_CHR;
945	    break;
946	case VLNK:
947	    ty = "VLNK";
948	    break;
949
950#if	defined(VSOCK)
951	case VSOCK:
952	    ty = "SOCK";
953	    break;
954#endif	/* defined(VSOCK) */
955
956	case VBAD:
957	    ty = "VBAD";
958	    break;
959	case VFIFO:
960	    ty = "FIFO";
961	    break;
962	default:
963	    (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
964	    ty = (char *)NULL;
965	}
966	if (ty)
967	    (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
968	Lf->ntype = Ntype;
969/*
970 * Handle some special cases:
971 *
972 * 	ioctl(fd, TIOCNOTTY) files;
973 *	memory node files;
974 *	/proc files.
975 */
976	if (type == VBAD)
977	    (void) snpf(Namech, Namechl, "(revoked)");
978
979#if	defined(HASBLKDEV)
980/*
981 * If this is a VBLK file and it's missing an inode number, try to
982 * supply one.
983 */
984	if ((Lf->inp_ty == 0) && (type == VBLK))
985	    find_bl_ino();
986#endif	/* defined(HASBLKDEV) */
987
988/*
989 * If this is a VCHR file and it's missing an inode number, try to
990 * supply one.
991 */
992	if ((Lf->inp_ty == 0) && (type == VCHR))
993	    find_ch_ino();
994/*
995 * Test for specified file.
996 */
997	if (Sfile && is_file_named((char *)NULL,
998				   ((type == VCHR) || (type == VBLK) ? 1
999								     : 0)))
1000	    Lf->sf |= SELNM;
1001/*
1002 * Enter name characters.
1003 */
1004	if (Namech[0])
1005	    enter_nm(Namech);
1006}
1007
1008
1009#if	DARWINV>=800
1010/*
1011 * readvname() - read vnode's path name
1012 */
1013
1014static int
1015readvname(addr, buf, buflen)
1016	KA_T addr;			/* kernel v_path address */
1017	char *buf;			/* receiving buffer */
1018	int buflen;			/* sizeof(buf) */
1019{
1020	int n, rl;
1021/*
1022 * Read the name 32 characters at a time, until a NUL character
1023 * has been read or the buffer has been filled.
1024 */
1025	for (n = 0; n < buflen; addr += 32, n += 32) {
1026	    rl = buflen - n;
1027	    if (rl > 32)
1028		rl = 32;
1029	    if (kread(addr, &buf[n], rl))
1030		return(0);
1031	    buf[n + rl] = '\0';
1032	    if ((rl = (int)strlen(&buf[n])) < 32) {
1033		return(n + rl);
1034	    }
1035	}
1036	return(0);
1037}
1038#endif	/* DARWINV>=800 */
1039