blob: d634c6216228f9a753587d49e46db0409b4ad422 [file] [log] [blame]
/*
* dnode.c - Darwin node functions for /dev/kmem-based lsof
*/
/*
* Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Victor A. Abell
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
static char *rcsid = "$Id: dnode.c,v 1.11 2006/03/27 23:24:50 abe Exp $";
#endif
#include "lsof.h"
/*
* Local function prototypes
*/
#if DARWINV<600
_PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, dev_t *rdr, INODETYPE *ir));
#endif /* DARWINV<600 */
#if DARWINV>=800
_PROTOTYPE(static char *getvpath,(KA_T va, struct vnode *rv));
_PROTOTYPE(static int readvname,(KA_T addr, char *buf, int buflen));
#endif /* DARWINV>=800 */
#if DARWINV>=800
/*
* getvpath() - get vnode path
* adapted from build_path() (.../bsd/vfs/vfs_subr.c)
*/
static char *
getvpath(va, rv)
KA_T va; /* kernel address of the rightmost
* vnode in the path */
struct vnode *rv; /* pointer to rightmost vnode */
{
char *ap;
static char *bp = (char *)NULL;
static size_t bl = (size_t)(MAXPATHLEN + MAXPATHLEN + 1);
static char *cb = (char *)NULL;
static size_t cbl = (size_t)0;
static int ce = 0;
struct mount mb;
int pl, vnl;
char *pp, vn[MAXPATHLEN+1];
struct vnode vb;
KA_T vas = va;
/*
* Initialize the path assembly.
*/
if (!bp) {
if (!(bp = (char *)malloc((MALLOC_S)bl))) {
(void) fprintf(stderr, "%s: no space (%d) for path assembly\n",
Pn, (int)bl);
Exit(1);
}
}
pp = bp + bl - 1;
*pp = '\0';
pl = 0;
/*
* Process the starting vnode.
*/
if (!va)
return(0);
if ((rv->v_flag & VROOT) && rv->v_mount) {
/*
* This is the root of a file system and it has a mount structure.
* Read the mount structure.
*/
if (kread((KA_T)rv->v_mount, (char *)&mb, sizeof(mb)))
return(0);
if (mb.mnt_flag & MNT_ROOTFS) {
/*
* This is the root file system, so the path is "/".
*/
pp--;
*pp = '/';
pl = 1;
goto getvpath_alloc;
} else {
/*
* Get the covered vnode's pointer and read it. Use it to
* form the path.
*/
if ((va = (KA_T)mb.mnt_vnodecovered)) {
if (readvnode(va, &vb))
return(0);
}
}
} else {
/*
* Use the supplied vnode.
*/
vb = *rv;
}
/*
* Accumulate the path from the vnode chain.
*/
while (va && ((KA_T)vb.v_parent != va)) {
if (!vb.v_name) {
/*
* If there is no name pointer or parent, the assembly is complete.
*/
if (vb.v_parent) {
/*
* It is an error if there is a parent but no name.
*/
return((char *)NULL);
}
break;
}
/*
* Read the name and add it to the assembly.
*/
if ((vnl = readvname((KA_T)vb.v_name, vn, sizeof(vn))) <= 0)
return((char *)NULL);
if ((vnl + 1 + pl + 1) > bl)
return((char *)NULL);
memmove((void *)(pp - vnl), (void *)vn, vnl);
pp -= (vnl + 1);
*pp = '/';
pl += vnl + 1;
if ((va == vas) && (vb.v_flag & VROOT)) {
/*
* This is the starting vnode and it is a root vnode. Read its
* mount structure.
*/
if (vb.v_mount) {
if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
return((char *)NULL);
if (mb.mnt_vnodecovered) {
/*
* If there's a covered vnode, read it and use it's parent
* vnode pointer.
*/
if ((va = (KA_T)mb.mnt_vnodecovered)) {
if (readvnode(va, &vb))
return((char *)NULL);
va = (KA_T)vb.v_parent;
}
} else
va = (KA_T)NULL;
} else
va = (KA_T)NULL;
} else
va = (KA_T)vb.v_parent;
/*
* If there's a parent vnode, read it.
*/
if (va) {
if (readvnode(va, &vb))
return((char *)NULL);
if ((vb.v_flag & VROOT) && vb.v_mount) {
/*
* The mount point has been reached. Read the mount structure
* and use its covered vnode pointer.
*/
if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
return((char *)NULL);
if ((va = (KA_T)mb.mnt_vnodecovered)) {
if (readvnode(va, &vb))
return((char *)NULL);
}
}
}
}
/*
* As a special case the following code attempts to trim a path that is
* larger than MAXPATHLEN by seeing if the lsof process CWD can be removed
* from the start of the path to make it MAXPATHLEN characters or less.
*/
if (pl > MAXPATHLEN) {
/*
* Get the cwd. If that can't be done, return an error.
*/
if (ce)
return((char *)NULL);
if (!cb) {
if (!(cb = (char *)malloc((MALLOC_S)(MAXPATHLEN + 1)))) {
(void) fprintf(stderr, "%s: no space (%d) for CWD\n",
Pn, (int)bl);
Exit(1);
}
if (!getcwd(cb, (size_t)(MAXPATHLEN + 1))) {
if (!Fwarn) {
(void) fprintf(stderr, "%s: WARNING: can't get CWD\n",
Pn);
}
ce = 1;
return((char *)NULL);
}
cb[MAXPATHLEN - 1] = '\0';
if (!(cbl = (size_t)strlen(cb))) {
if (!Fwarn) {
(void) fprintf(stderr, "%s: WARNING: CWD is NULL\n",
Pn);
}
ce = 1;
return((char *)NULL);
}
}
/*
* See if trimming the CWD shortens the path to MAXPATHLEN or less.
*/
if ((pl <= cbl) || strncmp(cb, pp, cbl))
return((char *)NULL);
pp += cbl;
pl -= cbl;
if (cb[cbl - 1] == '/') {
/*
* The CWD ends in a '/', so the path must not begin with one. If
* it does, no trimming can be done.
*/
if (*pp == '/')
return((char *)NULL);
} else {
/*
* The CWD doesn't end in a '/', so the path must begin with one.
* If it doesn't, no trimming can be done.
*/
if (*pp != '/')
return((char *)NULL);
/*
* Skip all leading path '/' characters. Some characters must
* remain.
*/
while ((pl > 0) && (*pp == '/')) {
pp++;
pl--;
}
if (!pl)
return((char *)NULL);
}
}
/*
* Allocate space for the assembled path, including terminator, and return its
* pointer.
*/
getvpath_alloc:
if (!(ap = (char *)malloc(pl + 1))) {
(void) fprintf(stderr, "%s: no getvpath space (%d)\n",
Pn, pl + 1);
Exit(1);
}
(void) memmove(ap, pp, pl + 1);
return(ap);
}
#endif /* DARWINV>=800 */
#if DARWINV<600
/*
* lkup_dev_tty() - look up /dev/tty
*/
static int
lkup_dev_tty(dr, rdr, ir)
dev_t *dr; /* place to return device number */
dev_t *rdr; /* place to return raw device number */
INODETYPE *ir; /* place to return inode number */
{
int i;
readdev(0);
for (i = 0; i < Ndev; i++) {
if (strcmp(Devtp[i].name, "/dev/tty") == 0) {
*dr = DevDev;
*rdr = Devtp[i].rdev;
*ir = (INODETYPE)Devtp[i].inode;
return(1);
}
}
return(-1);
}
#endif /* DARWINV<600 */
/*
* process_node() - process vnode
*/
void
process_node(va)
KA_T va; /* vnode kernel space address */
{
dev_t dev = (dev_t)0;
dev_t rdev = (dev_t)0;
unsigned char devs = 0;
unsigned char rdevs = 0;
#if DARWINV<800
struct devnode *d = (struct devnode *)NULL;
struct devnode db;
unsigned char lt;
char dev_ch[32];
# if defined(HASFDESCFS)
struct fdescnode *f = (struct fdescnode *)NULL;
struct fdescnode fb;
# endif /* defined(HASFDESCFS) */
static INODETYPE fi;
static dev_t fdev, frdev;
static int fs = 0;
struct inode *i = (struct inode *)NULL;
struct inode ib;
struct lockf lf, *lff, *lfp;
struct nfsnode *n = (struct nfsnode *)NULL;
struct nfsnode nb;
#else /* DARWINV>=800 */
struct stat sb;
char *vn;
#endif /* DARWINV<800 */
char *ty;
enum vtype type;
struct vnode *v, vb;
struct l_vfs *vfs;
#if DARWINV<600
struct hfsnode *h = (struct hfsnode *)NULL;
struct hfsnode hb;
struct hfsfilemeta *hm = (struct hfsfilemeta *)NULL;
struct hfsfilemeta hmb;
#else /* DARWINV>=600 */
# if DARWINV<800
struct cnode *h = (struct cnode *)NULL;
struct cnode hb;
struct filefork *hf = (struct filefork *)NULL;
struct filefork hfb;
# endif /* DARWINV<800 */
#endif /* DARWINV<600 */
#if defined(HAS9660FS)
dev_t iso_dev;
int iso_dev_def = 0;
INODETYPE iso_ino;
long iso_links;
int iso_stat = 0;
SZOFFTYPE iso_sz;
#endif /* defined(HAS9660FS) */
/*
* Read the vnode.
*/
if ( ! va) {
enter_nm("no vnode address");
return;
}
v = &vb;
if (readvnode(va, v)) {
enter_nm(Namech);
return;
}
type = v->v_type;
#if defined(HASNCACHE)
Lf->na = va;
# if defined(HASNCVPID)
Lf->id = v->v_id;
# endif /* defined(HASNCVPID) */
#endif /* defined(HASNCACHE) */
#if defined(HASFSTRUCT)
Lf->fna = va;
Lf->fsv |= FSV_NI;
#endif /* defined(HASFSTRUCT) */
/*
* Get the vnode type.
*/
if (!v->v_mount)
vfs = (struct l_vfs *)NULL;
else {
vfs = readvfs((KA_T)v->v_mount);
if (vfs) {
if (strcasecmp(vfs->typnm, "nfs") == 0)
Ntype = N_NFS;
#if DARWINV<130
else if (strcasecmp(vfs->typnm, "afpfs") == 0)
Ntype = N_AFPFS;
#endif /* DARWINV<130 */
}
}
if (Ntype == N_REGLR) {
switch (v->v_type) {
case VFIFO:
Ntype = N_FIFO;
break;
default:
break;
}
}
#if DARWINV<800
/*
* Define the specific node pointer.
*/
switch (v->v_tag) {
# if DARWINV>120
case VT_AFP:
break;
# endif /* DARWINV>120 */
# if DARWINV>120
case VT_CDDA:
break;
# endif /* DARWINV>120 */
# if DARWINV>120
case VT_CIFS:
break;
# endif /* DARWINV>120 */
case VT_DEVFS:
if (!v->v_data
|| kread((KA_T)v->v_data, (char *)&db, sizeof(db))) {
(void) snpf(Namech, Namechl, "no devfs node: %#x", v->v_data);
enter_nm(Namech);
return;
}
d = &db;
break;
# if defined(HASFDESCFS)
case VT_FDESC:
if (!v->v_data
|| kread((KA_T)v->v_data, (char *)&fb, sizeof(fb))) {
(void) snpf(Namech, Namechl, "no fdesc node: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
f = &fb;
break;
# endif /* defined(HASFDESCFS) */
case VT_HFS:
# if DARWINV<130
if (Ntype != N_AFPFS) {
# endif /* DARWINV<130 */
if (!v->v_data
|| kread((KA_T)v->v_data, (char *)&hb, sizeof(hb))) {
(void) snpf(Namech, Namechl, "no hfs node: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
h = &hb;
# if DARWINV<600
if (!h->h_meta
|| kread((KA_T)h->h_meta, (char *)&hmb, sizeof(hmb))) {
(void) snpf(Namech, Namechl, "no hfs node metadata: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
hm = &hmb;
# else /* DARWINV>=600 */
if (v->v_type == VDIR)
break;
if (h->c_rsrc_vp == v)
hf = h->c_rsrcfork;
else
hf = h->c_datafork;
if (!hf
|| kread((KA_T)hf, (char *)&hfb, sizeof(hfb))) {
(void) snpf(Namech, Namechl, "no hfs node fork: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
hf = &hfb;
# endif /* DARWINV<600 */
# if DARWINV<130
}
# endif /* DARWINV<130 */
break;
# if defined(HAS9660FS)
case VT_ISOFS:
if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links,
&iso_sz))
{
(void) snpf(Namech, Namechl, "no iso node: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
iso_stat = 1;
break;
# endif /* defined(HAS9660FS) */
case VT_NFS:
if (!v->v_data
|| kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) {
(void) snpf(Namech, Namechl, "no nfs node: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
n = &nb;
break;
# if DARWINV>120
case VT_UDF:
break;
# endif /* DARWINV>120 */
case VT_UFS:
if (!v->v_data
|| kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) {
(void) snpf(Namech, Namechl, "no ufs node: %s",
print_kptr((KA_T)v->v_data, (char *)NULL, 0));
enter_nm(Namech);
return;
}
i = &ib;
if ((lff = i->i_lockf)) {
/*
* Determine the lock state.
*/
lfp = lff;
do {
if (kread((KA_T)lfp, (char *)&lf, sizeof(lf)))
break;
lt = 0;
switch (lf.lf_flags & (F_FLOCK|F_POSIX)) {
case F_FLOCK:
if (Cfp && (struct file *)lf.lf_id == Cfp)
lt = 1;
break;
case F_POSIX:
if ((KA_T)lf.lf_id == Kpa)
lt = 1;
break;
}
if (!lt)
continue;
if (lf.lf_start == (off_t)0
&& lf.lf_end == 0xffffffffffffffffLL)
lt = 1;
else
lt = 0;
if (lf.lf_type == F_RDLCK)
Lf->lock = lt ? 'R' : 'r';
else if (lf.lf_type == F_WRLCK)
Lf->lock = lt ? 'W' : 'w';
else if (lf.lf_type == (F_RDLCK | F_WRLCK))
Lf->lock = 'u';
break;
} while ((lfp = lf.lf_next) && lfp != lff);
}
break;
# if DARWINV>120
case VT_WEBDAV:
break;
# endif /* DARWINV>120 */
default:
if (v->v_type == VBAD || v->v_type == VNON)
break;
(void) snpf(Namech, Namechl, "unknown file system type: %d",
v->v_tag);
enter_nm(Namech);
return;
}
/*
* Get device and type for printing.
*/
if (n) {
dev = n->n_vattr.va_fsid;
devs = 1;
} else if (i) {
dev = i->i_dev;
devs = 1;
if ((type == VCHR) || (type == VBLK)) {
rdev = i->i_rdev ;
rdevs = 1;
}
}
# if defined(HASFDESCFS)
else if (f) {
if (f->fd_link
&& !kread((KA_T)f->fd_link, Namech, Namechl -1))
Namech[Namechl - 1] = '\0';
# if DARWINV<600
else if (f->fd_type == Fctty) {
if (fs == 0)
fs = lkup_dev_tty(&fdev, &frdev, &fi);
if (fs == 1) {
dev = fdev;
rdev = frdev;
devs = Lf->inp_ty = rdevs = 1;
Lf->inode = fi;
}
}
}
# endif /* DARWINV<600 */
# endif /* defined(HASFDESCFS) */
else if (h) {
# if DARWINV<600
dev = hm->h_dev;
# else /* DARWINV>=600 */
dev = h->c_dev;
# endif /* DARWINV<600 */
devs = 1;
if ((type == VCHR) || (type == VBLK)) {
# if DARWINV<600
rdev = hm->h_rdev;
# else /* DARWINV>=600 */
rdev = h->c_rdev;
# endif /* DARWINV<600 */
rdevs = 1;
}
} else if (d) {
dev = DevDev;
devs = 1;
rdev = d->dn_typeinfo.dev;
rdevs = 1;
}
# if defined(HAS9660FS)
else if (iso_stat && iso_dev_def) {
dev = iso_dev;
devs = Lf->inp_ty = 1;
}
# endif /* defined(HAS9660FS) */
/*
* Obtain the inode number.
*/
if (i) {
Lf->inode = (INODETYPE)i->i_number;
Lf->inp_ty = 1;
} else if (n) {
Lf->inode = (INODETYPE)n->n_vattr.va_fileid;
Lf->inp_ty = 1;
} else if (h) {
# if DARWINV<600
Lf->inode = (INODETYPE)hm->h_nodeID;
# else /* DARWINV>=600 */
Lf->inode = (INODETYPE)h->c_fileid;
# endif /* DARWINV<600 */
Lf->inp_ty = 1;
}
# if defined(HAS9660FS)
else if (iso_stat) {
Lf->inode = iso_ino;
Lf->inp_ty = 1;
}
# endif /* defined(HAS9660FS) */
/*
* Obtain the file size.
*/
if (Foffset)
Lf->off_def = 1;
else {
switch (Ntype) {
case N_FIFO:
if (!Fsize)
Lf->off_def = 1;
break;
case N_NFS:
if (n) {
Lf->sz = (SZOFFTYPE)n->n_vattr.va_size;
Lf->sz_def = 1;
}
break;
# if DARWINV<130
case N_AFPFS:
break;
# endif /* DARWINV<130 */
case N_REGLR:
if (type == VREG || type == VDIR) {
if (i) {
Lf->sz = (SZOFFTYPE)i->i_size;
Lf->sz_def = 1;
} else if (h) {
# if DARWINV<600
Lf->sz = (type == VDIR) ? (SZOFFTYPE)hm->h_size
: (SZOFFTYPE)h->fcbEOF;
# else /* DARWINV>=600 */
if (type == VDIR)
Lf->sz = (SZOFFTYPE)h->c_nlink * 128;
else
Lf->sz = (SZOFFTYPE)hf->ff_size;
# endif /* DARWINV<600 */
Lf->sz_def = 1;
}
# if defined(HAS9660FS)
else if (iso_stat) {
Lf->sz = (SZOFFTYPE)iso_sz;
Lf->sz_def = 1;
}
# endif /* defined(HAS9660FS) */
}
else if ((type == VCHR || type == VBLK) && !Fsize)
Lf->off_def = 1;
break;
}
}
/*
* Record the link count.
*/
if (Fnlink) {
switch(Ntype) {
case N_NFS:
if (n) {
Lf->nlink = (long)n->n_vattr.va_nlink;
Lf->nlink_def = 1;
}
break;
# if DARWINV<130
case N_AFPFS:
break;
# endif /* DARWINV<130 */
case N_REGLR:
if (i) {
Lf->nlink = (long)i->i_nlink;
Lf->nlink_def = 1;
} else if (h) {
# if DARWINV<600
Lf->nlink = (long)hm->h_nlink;
# else /* DARWINV>=600 */
Lf->nlink = (long)h->c_nlink;
# endif /* DARWINV<600 */
Lf->nlink_def = 1;
}
# if defined(HAS9660FS)
else if (iso_stat) {
Lf->nlink = iso_links;
Lf->nlink_def = 1;
}
# endif /* defined(HAS9660FS) */
break;
}
if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
Lf->sf |= SELNLINK;
}
#else /* DARWINV>=800 */
/*
* Process a vnode for Darwin >= 8.0.
*/
if ((vn = getvpath(va, v))) {
/*
* If the vnode yields a path, get the file's information by doing
* a "safe" stat(2) of the path.
*/
if (!statsafely(vn, &sb)) {
/*
* Save file size or offset.
*/
if (Foffset) {
Lf->off_def = 1;
} else {
switch (Ntype) {
case N_FIFO:
if (!Fsize)
Lf->off_def = 1;
break;
case N_NFS:
case N_REGLR:
if (type == VREG || type == VDIR) {
Lf->sz = sb.st_size;
Lf->sz_def = 1;
} else if ((type == VCHR || type == VBLK) && !Fsize)
Lf->off_def = 1;
break;
}
}
/*
* Save node number.
*/
Lf->inode = (INODETYPE)sb.st_ino;
Lf->inp_ty = 1;
/*
* Optionally save link count.
*/
if (Fnlink) {
Lf->nlink = sb.st_nlink;
Lf->nlink_def = 1;
}
/*
* Save device number and path.
*/
switch (v->v_tag) {
case VT_DEVFS:
if (vn)
(void) free((FREE_P *)vn);
dev = DevDev;
devs = 1;
break;
default :
Lf->V_path = vn;
dev = sb.st_dev;
devs = 1;
break;
}
/*
* Save character and block device number.
*/
if ((type == VCHR) || (type == VBLK)) {
rdev = sb.st_rdev;
rdevs = 1;
}
} else {
/*
* Indicate a stat(2) failure in Namech[].
*/
(void) snpf(Namech, Namechl, "stat(%s): %s", vn,
strerror(errno));
(void) free((FREE_P *)vn);
}
/*
* Record an NFS file.
*/
if (vfs && !strcmp(vfs->typnm, "nfs"))
Ntype = N_NFS;
}
#endif /* DARWINV>=800 */
/*
* Record an NFS file selection.
*/
if (Ntype == N_NFS && Fnfs)
Lf->sf |= SELNFS;
/*
* Save the file system names.
*/
if (vfs) {
Lf->fsdir = vfs->dir;
Lf->fsdev = vfs->fsname;
}
/*
* Save the device numbers and their states.
*
* Format the vnode type, and possibly the device name.
*/
Lf->dev = dev;
Lf->dev_def = devs;
Lf->rdev = rdev;
Lf->rdev_def = rdevs;
switch (type) {
case VNON:
ty ="VNON";
break;
case VREG:
ty = "VREG";
break;
case VDIR:
ty = "VDIR";
break;
case VBLK:
ty = "VBLK";
Ntype = N_BLK;
break;
case VCHR:
ty = "VCHR";
Ntype = N_CHR;
break;
case VLNK:
ty = "VLNK";
break;
#if defined(VSOCK)
case VSOCK:
ty = "SOCK";
break;
#endif /* defined(VSOCK) */
case VBAD:
ty = "VBAD";
break;
case VFIFO:
ty = "FIFO";
break;
default:
(void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
ty = (char *)NULL;
}
if (ty)
(void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
Lf->ntype = Ntype;
/*
* Handle some special cases:
*
* ioctl(fd, TIOCNOTTY) files;
* memory node files;
* /proc files.
*/
if (type == VBAD)
(void) snpf(Namech, Namechl, "(revoked)");
#if defined(HASBLKDEV)
/*
* If this is a VBLK file and it's missing an inode number, try to
* supply one.
*/
if ((Lf->inp_ty == 0) && (type == VBLK))
find_bl_ino();
#endif /* defined(HASBLKDEV) */
/*
* If this is a VCHR file and it's missing an inode number, try to
* supply one.
*/
if ((Lf->inp_ty == 0) && (type == VCHR))
find_ch_ino();
/*
* Test for specified file.
*/
if (Sfile && is_file_named((char *)NULL,
((type == VCHR) || (type == VBLK) ? 1
: 0)))
Lf->sf |= SELNM;
/*
* Enter name characters.
*/
if (Namech[0])
enter_nm(Namech);
}
#if DARWINV>=800
/*
* readvname() - read vnode's path name
*/
static int
readvname(addr, buf, buflen)
KA_T addr; /* kernel v_path address */
char *buf; /* receiving buffer */
int buflen; /* sizeof(buf) */
{
int n, rl;
/*
* Read the name 32 characters at a time, until a NUL character
* has been read or the buffer has been filled.
*/
for (n = 0; n < buflen; addr += 32, n += 32) {
rl = buflen - n;
if (rl > 32)
rl = 32;
if (kread(addr, &buf[n], rl))
return(0);
buf[n + rl] = '\0';
if ((rl = (int)strlen(&buf[n])) < 32) {
return(n + rl);
}
}
return(0);
}
#endif /* DARWINV>=800 */