Blame lib/rnch.c

Packit Service 603f59
/*
Packit Service 603f59
 * rnch.c -- Sun format name cache functions for lsof library
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
Packit Service 603f59
 * 47907.  All rights reserved.
Packit Service 603f59
 *
Packit Service 603f59
 * Written by Victor A. Abell
Packit Service 603f59
 *
Packit Service 603f59
 * This software is not subject to any license of the American Telephone
Packit Service 603f59
 * and Telegraph Company or the Regents of the University of California.
Packit Service 603f59
 *
Packit Service 603f59
 * Permission is granted to anyone to use this software for any purpose on
Packit Service 603f59
 * any computer system, and to alter it and redistribute it freely, subject
Packit Service 603f59
 * to the following restrictions:
Packit Service 603f59
 *
Packit Service 603f59
 * 1. Neither the authors nor Purdue University are responsible for any
Packit Service 603f59
 *    consequences of the use of this software.
Packit Service 603f59
 *
Packit Service 603f59
 * 2. The origin of this software must not be misrepresented, either by
Packit Service 603f59
 *    explicit claim or by omission.  Credit to the authors and Purdue
Packit Service 603f59
 *    University must appear in documentation and sources.
Packit Service 603f59
 *
Packit Service 603f59
 * 3. Altered versions must be plainly marked as such, and must not be
Packit Service 603f59
 *    misrepresented as being the original software.
Packit Service 603f59
 *
Packit Service 603f59
 * 4. This notice may not be removed or altered.
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
#include "../machine.h"
Packit Service 603f59
Packit Service 603f59
#if	defined(HASNCACHE) && defined(USE_LIB_RNCH)
Packit Service 603f59
Packit Service 603f59
# if	!defined(lint)
Packit Service 603f59
static char copyright[] =
Packit Service 603f59
"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
Packit Service 603f59
static char *rcsid = "$Id: rnch.c,v 1.11 2008/10/21 16:13:23 abe Exp $";
Packit Service 603f59
# endif	/* !defined(lint) */
Packit Service 603f59
Packit Service 603f59
#include "../lsof.h"
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * rnch.c - read Sun format (struct ncache) name cache
Packit Service 603f59
 *
Packit Service 603f59
 * This code is effective only when HASNCACHE is defined.
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * The caller must:
Packit Service 603f59
 *
Packit Service 603f59
 *	#include the relevant header file -- e.g., <sys/dnlc.h>.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define X_NCSIZE as the nickname for the kernel cache size variable,
Packit Service 603f59
 *	or, if X_NCSIZE is undefined, define FIXED_NCSIZE as the size of the
Packit Service 603f59
 *	kernel cache.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define X_NCACHE as the nickname for the kernel cache address and
Packit Service 603f59
 *	define ADDR_NCACHE if the address is the address of the cache,
Packit Service 603f59
 *	rather than the address of a pointer to it.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_NXT if the kernel's name cache is a linked list, starting
Packit Service 603f59
 *	at the X_NCACHE address, rather than a table, starting at that address.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define any of the following casts that differ from their defaults:
Packit Service 603f59
 *
Packit Service 603f59
 *		NCACHE_SZ_CAST	cast for X_NCACHE (default int)
Packit Service 603f59
 *
Packit Service 603f59
 * The caller may:
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_DP	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				parent vnode pointer.
Packit Service 603f59
 *
Packit Service 603f59
 *				Default: dp
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_NAME	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				name.
Packit Service 603f59
 *
Packit Service 603f59
 *				Default: name
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_NAMLEN	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				name length.
Packit Service 603f59
 *
Packit Service 603f59
 *				Deafult: namlen
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_NEGVN	as the name of the name list element
Packit Service 603f59
 *				whose value is a vnode address to
Packit Service 603f59
 *				ignore when loading the kernel name
Packit Service 603f59
 *				cache.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_NODEID	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				vnode's capability ID.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_PARID	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				parent vnode's capability ID.
Packit Service 603f59
 *
Packit Service 603f59
 *	Define NCACHE_VP	as the name of the element in the
Packit Service 603f59
 *				ncache structure that contains the
Packit Service 603f59
 *				vnode pointer.
Packit Service 603f59
 *
Packit Service 603f59
 *				Default: vp
Packit Service 603f59
 *
Packit Service 603f59
 * Note: if NCACHE_NODEID is defined, then NCACHE_PARID must be defined.
Packit Service 603f59
 *
Packit Service 603f59
 *
Packit Service 603f59
 * The caller must:
Packit Service 603f59
 *
Packit Service 603f59
 *	Define this prototype for ncache_load():
Packit Service 603f59
 *
Packit Service 603f59
 *		_PROTOTYPE(void ncache_load,(void));
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * Local static values
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
static int Mch;				/* name cache hash mask */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NC_CAST)
Packit Service 603f59
#define	NCACHE_SZ_CAST	int
Packit Service 603f59
# endif	/* !defined(NCACHE_NC_CAST) */
Packit Service 603f59
Packit Service 603f59
static NCACHE_SZ_CAST Nc = 0;		/* size of name cache */
Packit Service 603f59
static int Nch = 0;			/* size of name cache hash pointer
Packit Service 603f59
					 * table */
Packit Service 603f59
struct l_nch {
Packit Service 603f59
	KA_T vp;			/* vnode address */
Packit Service 603f59
	KA_T dp;			/* parent vnode address */
Packit Service 603f59
	struct l_nch *pa;		/* parent Ncache address */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	unsigned long id;		/* node's capability ID */
Packit Service 603f59
	unsigned long did;		/* parent node's capability ID */
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	char *nm;			/* name */
Packit Service 603f59
	int nl;				/* name length */
Packit Service 603f59
};
Packit Service 603f59
Packit Service 603f59
static struct l_nch *Ncache = (struct l_nch *)NULL;
Packit Service 603f59
					/* the local name cache */
Packit Service 603f59
static struct l_nch **Nchash = (struct l_nch **)NULL;
Packit Service 603f59
					/* Ncache hash pointers */
Packit Service 603f59
static int Ncfirst = 1;			/* first-call status */
Packit Service 603f59
Packit Service 603f59
# if 	defined(NCACHE_NEGVN)
Packit Service 603f59
static KA_T NegVN = (KA_T)NULL;		/* negative vnode address */
Packit Service 603f59
static int NegVNSt = 0;			/* NegVN status: 0 = not loaded */
Packit Service 603f59
# endif	/* defined(NCACHE_NEGVN) */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long i, KA_T v));
Packit Service 603f59
#define ncachehash(i,v)		Nchash+(((((int)(v)>>2)+((int)(i)))*31415)&Mch)
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T v));
Packit Service 603f59
#define ncachehash(v)		Nchash+((((int)(v)>>2)*31415)&Mch)
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
_PROTOTYPE(static int ncache_isroot,(KA_T va, char *cp));
Packit Service 603f59
Packit Service 603f59
#define DEFNCACHESZ	1024	/* local size if X_NCSIZE kernel value < 1 */
Packit Service 603f59
#define	LNCHINCRSZ	64	/* local size increment */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_DP)
Packit Service 603f59
#define	NCACHE_DP	dp
Packit Service 603f59
# endif	/* !defined(NCACHE_DP) */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NAME)
Packit Service 603f59
#define	NCACHE_NAME	name
Packit Service 603f59
# endif	/* !defined(NCACHE_NAME) */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NAMLEN)
Packit Service 603f59
#define	NCACHE_NAMLEN	namlen
Packit Service 603f59
# endif	/* !defined(NCACHE_NAMLEN) */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_VP)
Packit Service 603f59
#define	NCACHE_VP	vp
Packit Service 603f59
# endif	/* !defined(NCACHE_VP) */
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * ncache_addr() - look up a node's local ncache address
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
static struct l_nch *
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
ncache_addr(i, v)
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
ncache_addr(v)
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	unsigned long i;			/* capability ID */
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	KA_T v;					/* vnode's address */
Packit Service 603f59
{
Packit Service 603f59
	struct l_nch **hp;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	for (hp = ncachehash(i, v); *hp; hp++)
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
	for (hp = ncachehash(v); *hp; hp++)
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	{
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	    if ((*hp)->vp == v && (*hp)->id == i)
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
	    if ((*hp)->vp == v)
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
		return(*hp);
Packit Service 603f59
	}
Packit Service 603f59
	return((struct l_nch *)NULL);
Packit Service 603f59
}
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * ncache_isroot() - is head of name cache path a file system root?
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
static int
Packit Service 603f59
ncache_isroot(va, cp)
Packit Service 603f59
	KA_T va;			/* kernel vnode address */
Packit Service 603f59
	char *cp;			/* partial path */
Packit Service 603f59
{
Packit Service 603f59
	char buf[MAXPATHLEN];
Packit Service 603f59
	int i;
Packit Service 603f59
	MALLOC_S len;
Packit Service 603f59
	struct mounts *mtp;
Packit Service 603f59
	struct stat sb;
Packit Service 603f59
	struct vnode v;
Packit Service 603f59
	static int vca = 0;
Packit Service 603f59
	static int vcn = 0;
Packit Service 603f59
	static KA_T *vc = (KA_T *)NULL;
Packit Service 603f59
Packit Service 603f59
	if (!va)
Packit Service 603f59
	    return(0);
Packit Service 603f59
/*
Packit Service 603f59
 * Search the root vnode cache.
Packit Service 603f59
 */
Packit Service 603f59
	for (i = 0; i < vcn; i++) {
Packit Service 603f59
	    if (va == vc[i])
Packit Service 603f59
		return(1);
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Read the vnode and see if it's a VDIR node with the VROOT flag set.  If
Packit Service 603f59
 * it is, then the path is complete.
Packit Service 603f59
 *
Packit Service 603f59
 * If it isn't, and if the file has an inode number, search the mount table
Packit Service 603f59
 * and see if the file system's inode number is known.  If it is, form the
Packit Service 603f59
 * possible full path, safely stat() it, and see if it's inode number matches
Packit Service 603f59
 * the one we have for this file.  If it does, then the path is complete.
Packit Service 603f59
 */
Packit Service 603f59
	if (kread((KA_T)va, (char *)&v, sizeof(v))
Packit Service 603f59
	||  v.v_type != VDIR || !(v.v_flag & VROOT)) {
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * The vnode tests failed.  Try the inode tests.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (Lf->inp_ty != 1 || !Lf->inode
Packit Service 603f59
	    ||  !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1)
Packit Service 603f59
		return(0);
Packit Service 603f59
	    if ((len + 1 + strlen(cp) + 1) > sizeof(buf))
Packit Service 603f59
		return(0);
Packit Service 603f59
	    for (mtp = readmnt(); mtp; mtp = mtp->next) {
Packit Service 603f59
		if (!mtp->dir || !mtp->inode)
Packit Service 603f59
		    continue;
Packit Service 603f59
		if (strcmp(Lf->fsdir, mtp->dir) == 0)
Packit Service 603f59
		    break;
Packit Service 603f59
	    }
Packit Service 603f59
	    if (!mtp)
Packit Service 603f59
		return(0);
Packit Service 603f59
	    (void) strcpy(buf, Lf->fsdir);
Packit Service 603f59
	    if (buf[len - 1] != '/')
Packit Service 603f59
		buf[len++] = '/';
Packit Service 603f59
	    (void) strcpy(&buf[len], cp);
Packit Service 603f59
	    if (statsafely(buf, &sb) != 0
Packit Service 603f59
	    ||  (unsigned long)sb.st_ino != Lf->inode)
Packit Service 603f59
		return(0);
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Add the vnode address to the root vnode cache.
Packit Service 603f59
 */
Packit Service 603f59
	if (vcn >= vca) {
Packit Service 603f59
	    vca += 10;
Packit Service 603f59
	    len = (MALLOC_S)(vca * sizeof(KA_T));
Packit Service 603f59
	    if (!vc)
Packit Service 603f59
		vc = (KA_T *)malloc(len);
Packit Service 603f59
	    else
Packit Service 603f59
		vc = (KA_T *)realloc(vc, len);
Packit Service 603f59
	    if (!vc) {
Packit Service 603f59
		(void) fprintf(stderr, "%s: no space for root vnode table\n",
Packit Service 603f59
		    Pn);
Packit Service 603f59
		Exit(1);
Packit Service 603f59
	    }
Packit Service 603f59
	}
Packit Service 603f59
	vc[vcn++] = va;
Packit Service 603f59
	return(1);
Packit Service 603f59
}
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * ncache_load() - load the kernel's name cache
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
void
Packit Service 603f59
ncache_load()
Packit Service 603f59
{
Packit Service 603f59
	char *cp, *np;
Packit Service 603f59
	struct l_nch **hp, *lc;
Packit Service 603f59
	int i, len, n;
Packit Service 603f59
	static int iNc = 0;
Packit Service 603f59
	struct ncache *kc;
Packit Service 603f59
	static KA_T kp = (KA_T)NULL;
Packit Service 603f59
	KA_T v;
Packit Service 603f59
Packit Service 603f59
# if	defined(HASDNLCPTR)
Packit Service 603f59
	static int na = 0;
Packit Service 603f59
	static char *nb = (char *)NULL;
Packit Service 603f59
# endif	/* defined(HASDNLCPTR) */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	static KA_T kf;
Packit Service 603f59
	struct ncache nc;
Packit Service 603f59
# else	/* !defined(NCACHE_NXT) */
Packit Service 603f59
	static struct ncache *kca = (struct ncache *)NULL;
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	if (!Fncache)
Packit Service 603f59
	    return;
Packit Service 603f59
	if (Ncfirst) {
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Do startup (first-time) functions.
Packit Service 603f59
	 */
Packit Service 603f59
	    Ncfirst = 0;
Packit Service 603f59
	/*
Packit Service 603f59
	 * Establish kernel cache size.
Packit Service 603f59
	 */
Packit Service 603f59
Packit Service 603f59
# if	defined(X_NCSIZE)
Packit Service 603f59
	    v = (KA_T)0;
Packit Service 603f59
	    if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0
Packit Service 603f59
	    ||  !v
Packit Service 603f59
	    ||  kread((KA_T)v, (char *)&Nc, sizeof(Nc)))
Packit Service 603f59
	    {
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		(void) fprintf(stderr,
Packit Service 603f59
		    "%s: WARNING: can't read name cache size: %s\n",
Packit Service 603f59
			Pn, print_kptr(v, (char *)NULL, 0));
Packit Service 603f59
		iNc = Nc = 0;
Packit Service 603f59
		return;
Packit Service 603f59
	    }
Packit Service 603f59
	    iNc = Nc;
Packit Service 603f59
# else	/* !defined(X_NCSIZE) */
Packit Service 603f59
	    iNc = Nc = FIXED_NCSIZE;
Packit Service 603f59
# endif	/* defined(X_NCSIZE) */
Packit Service 603f59
Packit Service 603f59
	    if (Nc < 1) {
Packit Service 603f59
		if (!Fwarn) {
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: WARNING: kernel name cache size: %d\n", Pn, Nc);
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"      Cache size assumed to be: %d\n", DEFNCACHESZ);
Packit Service 603f59
		}
Packit Service 603f59
		iNc = Nc = DEFNCACHESZ;
Packit Service 603f59
	    }
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NEGVN)
Packit Service 603f59
	/*
Packit Service 603f59
	 * Get negative vnode address.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (!NegVNSt) {
Packit Service 603f59
		if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN)
Packit Service 603f59
		< 0)
Packit Service 603f59
		    NegVN = (KA_T)NULL;
Packit Service 603f59
		NegVNSt = 1;
Packit Service 603f59
	    }
Packit Service 603f59
# endif	/* defined(NCACHE_NEGVN) */
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Establish kernel cache address.
Packit Service 603f59
	 */
Packit Service 603f59
Packit Service 603f59
# if	defined(ADDR_NCACHE)
Packit Service 603f59
	    kp = (KA_T)0;
Packit Service 603f59
	    if (get_Nl_value(X_NCACHE,(struct drive_Nl *)NULL,(KA_T *)&kp) < 0
Packit Service 603f59
	    || !kp) {
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: WARNING: no name cache address\n", Pn);
Packit Service 603f59
		iNc = Nc = 0;
Packit Service 603f59
		return;
Packit Service 603f59
	    }
Packit Service 603f59
# else	/* !defined(ADDR_NCACHE) */
Packit Service 603f59
	    v = (KA_T)0;
Packit Service 603f59
	    if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0
Packit Service 603f59
	    || !v
Packit Service 603f59
	    ||  kread((KA_T)v, (char *)&kp, sizeof(kp))) {
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: WARNING: can't read name cache ptr: %s\n",
Packit Service 603f59
			Pn, print_kptr(v, (char *)NULL, 0));
Packit Service 603f59
		iNc = Nc = 0;
Packit Service 603f59
		return;
Packit Service 603f59
	    }
Packit Service 603f59
# endif	/* defined(ADDR_NCACHE) */
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Allocate space for a local copy of the kernel's cache.
Packit Service 603f59
	 */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NXT)
Packit Service 603f59
	    len = Nc * sizeof(struct ncache);
Packit Service 603f59
	    if (!(kca = (struct ncache *)malloc((MALLOC_S)len))) {
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: can't allocate name cache space: %d\n", Pn, len);
Packit Service 603f59
		Exit(1);
Packit Service 603f59
	    }
Packit Service 603f59
# endif	/* !defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Allocate space for the local cache.
Packit Service 603f59
	 */
Packit Service 603f59
	    len = Nc * sizeof(struct l_nch);
Packit Service 603f59
	    if (!(Ncache = (struct l_nch *)calloc(Nc, sizeof(struct l_nch)))) {
Packit Service 603f59
Packit Service 603f59
no_local_space:
Packit Service 603f59
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
		      "%s: no space for %d byte local name cache\n", Pn, len);
Packit Service 603f59
		Exit(1);
Packit Service 603f59
	    }
Packit Service 603f59
	} else {
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Do setup for repeat calls.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (!iNc)
Packit Service 603f59
		return;
Packit Service 603f59
	    if (Nchash) {
Packit Service 603f59
		(void) free((FREE_P *)Nchash);
Packit Service 603f59
		Nchash = (struct l_nch **)NULL;
Packit Service 603f59
	    }
Packit Service 603f59
	    if (Ncache) {
Packit Service 603f59
Packit Service 603f59
	    /*
Packit Service 603f59
	     * Free space malloc'd to names in local name cache.
Packit Service 603f59
	     */
Packit Service 603f59
	        for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
Packit Service 603f59
		    if (lc->nm) {
Packit Service 603f59
			(void) free((FREE_P *)lc->nm);
Packit Service 603f59
			lc->nm = (char *)NULL;
Packit Service 603f59
		    }
Packit Service 603f59
	        }
Packit Service 603f59
	    }
Packit Service 603f59
	    Nc = iNc;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	    kp = kf;
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	}
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NXT)
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * Read the kernel's name cache.
Packit Service 603f59
 */
Packit Service 603f59
	if (kread(kp, (char *)kca, (Nc * sizeof(struct ncache)))) {
Packit Service 603f59
	    if (!Fwarn)
Packit Service 603f59
		(void) fprintf(stderr,
Packit Service 603f59
		    "%s: WARNING: can't read kernel's name cache: %s\n",
Packit Service 603f59
		    Pn, print_kptr(kp, (char *)NULL, 0));
Packit Service 603f59
	    Nc = 0;
Packit Service 603f59
	    return;
Packit Service 603f59
	}
Packit Service 603f59
# endif	/* !defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * Build a local copy of the kernel name cache.
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	for (i = iNc * 16, kc = &nc, kf = kp, lc = Ncache, n = 0; kp; )
Packit Service 603f59
# else	/* !defined(NCACHE_NXT) */
Packit Service 603f59
	for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++)
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	{
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	    if (kread(kp, (char *)kc, sizeof(nc)))
Packit Service 603f59
		break;
Packit Service 603f59
	    if ((kp = (KA_T)kc->NCACHE_NXT) == kf)
Packit Service 603f59
		kp = (KA_T)NULL;
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	    if (!kc->NCACHE_VP || (len = kc->NCACHE_NAMLEN) < 1)
Packit Service 603f59
		continue;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NEGVN)
Packit Service 603f59
	    if (NegVN && ((KA_T)kc->NCACHE_VP == NegVN))
Packit Service 603f59
		continue;
Packit Service 603f59
# endif	/* defined(NCACHE_NEGVN) */
Packit Service 603f59
Packit Service 603f59
# if	defined(HASDNLCPTR)
Packit Service 603f59
	/*
Packit Service 603f59
	 * Read name from kernel to a temporary buffer.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (len > na) {
Packit Service 603f59
		na = len;
Packit Service 603f59
		if (!nb)
Packit Service 603f59
		    nb = (char *)malloc(na);
Packit Service 603f59
		else
Packit Service 603f59
		    nb = (char *)realloc((MALLOC_P *)nb, na);
Packit Service 603f59
		if (!nb) {
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: can't allocate %d byte temporary name buffer\n",
Packit Service 603f59
			Pn, na);
Packit Service 603f59
		    Exit(1);
Packit Service 603f59
		}
Packit Service 603f59
	    }
Packit Service 603f59
	    if (!kc->NCACHE_NAME || kread((KA_T)kc->NCACHE_NAME, nb, len))
Packit Service 603f59
		continue;
Packit Service 603f59
	    np = nb;
Packit Service 603f59
# else	/* !defined(HASDNLCPTR) */
Packit Service 603f59
	/*
Packit Service 603f59
	 * Use name that is in the kernel cache entry.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (len > NC_NAMLEN)
Packit Service 603f59
		continue;
Packit Service 603f59
	    np = kc->NCACHE_NAME;
Packit Service 603f59
# endif	/* defined(HASDNLCPTR) */
Packit Service 603f59
Packit Service 603f59
	    if (len < 3 && *np == '.') {
Packit Service 603f59
		if (len == 1 || (len == 2 && np[1] == '.'))
Packit Service 603f59
		    continue;
Packit Service 603f59
	    }
Packit Service 603f59
	/*
Packit Service 603f59
	 * Allocate space for name in local cache entry.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (!(cp = (char *)malloc(len + 1))) {
Packit Service 603f59
		(void) fprintf(stderr,
Packit Service 603f59
		    "%s: can't allocate %d bytes for name cache name: %s\n",
Packit Service 603f59
		    Pn, len + 1, np);
Packit Service 603f59
		Exit(1);
Packit Service 603f59
	    }
Packit Service 603f59
	    (void) strncpy(cp, np, len);
Packit Service 603f59
	    cp[len] = '\0';
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	    if (n >= Nc) {
Packit Service 603f59
Packit Service 603f59
	    /*
Packit Service 603f59
	     * Allocate more local space to receive the kernel's linked
Packit Service 603f59
	     * entries.
Packit Service 603f59
	     */
Packit Service 603f59
		Nc += LNCHINCRSZ;
Packit Service 603f59
		if (!(Ncache = (struct l_nch *)realloc(Ncache,
Packit Service 603f59
		     (MALLOC_S)(Nc * sizeof(struct l_nch)))))
Packit Service 603f59
		{
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: no more space for %d entry local name cache\n",
Packit Service 603f59
			Pn, Nc);
Packit Service 603f59
		    Exit(1);
Packit Service 603f59
		}
Packit Service 603f59
		lc = &Ncache[n];
Packit Service 603f59
		iNc = Nc;
Packit Service 603f59
	    }
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * Complete the local cache entry.
Packit Service 603f59
	 */
Packit Service 603f59
	    lc->vp = (KA_T)kc->NCACHE_VP;
Packit Service 603f59
	    lc->dp = (KA_T)kc->NCACHE_DP;
Packit Service 603f59
	    lc->pa = (struct l_nch *)NULL;
Packit Service 603f59
	    lc->nm = cp;
Packit Service 603f59
	    lc->nl = len;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	    lc->id = (unsigned long)kc->NCACHE_NODEID;
Packit Service 603f59
	    lc->did = (unsigned long)kc->NCACHE_PARID;
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	    n++;
Packit Service 603f59
	    lc++;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NXT)
Packit Service 603f59
	    if (n >= i) {
Packit Service 603f59
		if (!Fwarn)
Packit Service 603f59
		    (void) fprintf(stderr,
Packit Service 603f59
			"%s: WARNING: name cache truncated at %d entries\n",
Packit Service 603f59
			Pn, n);
Packit Service 603f59
		break;
Packit Service 603f59
	    }
Packit Service 603f59
# endif	/* defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Reduce memory usage, as required.
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
# if	!defined(NCACHE_NXT)
Packit Service 603f59
	if (!RptTm)
Packit Service 603f59
	    (void) free((FREE_P *)kca);
Packit Service 603f59
# endif	/* !defined(NCACHE_NXT) */
Packit Service 603f59
Packit Service 603f59
	if (n < 1) {
Packit Service 603f59
	    if (!RptTm && Ncache) {
Packit Service 603f59
Packit Service 603f59
	    /*
Packit Service 603f59
	     * If not in repeat mode, free the space that has been malloc'd
Packit Service 603f59
	     * to the local name cache.
Packit Service 603f59
	     */
Packit Service 603f59
		for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
Packit Service 603f59
		    if (lc->nm) {
Packit Service 603f59
			(void) free((FREE_P *)lc->nm);
Packit Service 603f59
			lc->nm = (char *)NULL;
Packit Service 603f59
		    }
Packit Service 603f59
		}
Packit Service 603f59
		(void) free((FREE_P *)Ncache);
Packit Service 603f59
	 	Ncache = (struct l_nch *)NULL;
Packit Service 603f59
		Nc = 0;
Packit Service 603f59
	    }
Packit Service 603f59
	    if (!Fwarn)
Packit Service 603f59
		(void) fprintf(stderr,
Packit Service 603f59
		    "%s: WARNING: unusable name cache size: %d\n", Pn, n);
Packit Service 603f59
	    return;
Packit Service 603f59
	}
Packit Service 603f59
	if (n < Nc) {
Packit Service 603f59
	    Nc = n;
Packit Service 603f59
	    if (!RptTm) {
Packit Service 603f59
		len = Nc * sizeof(struct l_nch);
Packit Service 603f59
		if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
Packit Service 603f59
		    goto no_local_space;
Packit Service 603f59
	    }
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Build a hash table to locate Ncache entries.
Packit Service 603f59
 */
Packit Service 603f59
	for (Nch = 1; Nch < Nc; Nch <<= 1)
Packit Service 603f59
	    ;
Packit Service 603f59
	Nch <<= 1;
Packit Service 603f59
	Mch = Nch - 1;
Packit Service 603f59
	if (!(Nchash = (struct l_nch **)calloc(Nch+Nc, sizeof(struct l_nch *))))
Packit Service 603f59
	{
Packit Service 603f59
	    if (!Fwarn)
Packit Service 603f59
		(void) fprintf(stderr,
Packit Service 603f59
		    "%s: no space for %d name cache hash pointers\n",
Packit Service 603f59
		    Pn, Nch + Nc);
Packit Service 603f59
	    Exit(1);
Packit Service 603f59
	}
Packit Service 603f59
	for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	    for (hp = ncachehash(lc->id, lc->vp), n = 1; *hp; hp++)
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
	    for (hp = ncachehash(lc->vp), n = 1; *hp; hp++)
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	    {
Packit Service 603f59
		if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0
Packit Service 603f59
		&&  (*hp)->dp == lc->dp
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
		&&  (*hp)->id == lc->id && (*hp)->did == lc->did
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
		) {
Packit Service 603f59
		    n = 0;
Packit Service 603f59
		    break;
Packit Service 603f59
		}
Packit Service 603f59
	    }
Packit Service 603f59
	    if (n)
Packit Service 603f59
		*hp = lc;
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Make a final pass through the local cache and convert parent vnode
Packit Service 603f59
 * addresses to local name cache pointers.
Packit Service 603f59
 */
Packit Service 603f59
	for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
Packit Service 603f59
	    if (!lc->dp)
Packit Service 603f59
		continue;
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NEGVN)
Packit Service 603f59
	     if (NegVN && (lc->dp == NegVN)) {
Packit Service 603f59
		lc->pa = (struct l_nch *)NULL;
Packit Service 603f59
		continue;
Packit Service 603f59
	     }
Packit Service 603f59
# endif	/* defined(NCACHE_NEGVN) */
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	    lc->pa = ncache_addr(lc->did, lc->dp);
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
	    lc->pa = ncache_addr(lc->dp);
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
	
Packit Service 603f59
	}
Packit Service 603f59
}
Packit Service 603f59
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * ncache_lookup() - look up a node's name in the kernel's name cache
Packit Service 603f59
 */
Packit Service 603f59
Packit Service 603f59
char *
Packit Service 603f59
ncache_lookup(buf, blen, fp)
Packit Service 603f59
	char *buf;			/* receiving name buffer */
Packit Service 603f59
	int blen;			/* receiving buffer length */
Packit Service 603f59
	int *fp;			/* full path reply */
Packit Service 603f59
{
Packit Service 603f59
	char *cp = buf;
Packit Service 603f59
	struct l_nch *lc;
Packit Service 603f59
	struct mounts *mtp;
Packit Service 603f59
	int nl, rlen;
Packit Service 603f59
Packit Service 603f59
	*cp = '\0';
Packit Service 603f59
	*fp = 0;
Packit Service 603f59
Packit Service 603f59
# if	defined(HASFSINO)
Packit Service 603f59
/*
Packit Service 603f59
 * If the entry has an inode number that matches the inode number of the
Packit Service 603f59
 * file system mount point, return an empty path reply.  That tells the
Packit Service 603f59
 * caller to print the file system mount point name only.
Packit Service 603f59
 */
Packit Service 603f59
	if ((Lf->inp_ty == 1) && Lf->fs_ino && (Lf->inode == Lf->fs_ino))
Packit Service 603f59
	    return(cp);
Packit Service 603f59
# endif	/* defined(HASFSINO) */
Packit Service 603f59
Packit Service 603f59
/*
Packit Service 603f59
 * Look up the name cache entry for the node address.
Packit Service 603f59
 */
Packit Service 603f59
	if (!Nc
Packit Service 603f59
Packit Service 603f59
# if	defined(NCACHE_NODEID)
Packit Service 603f59
	||  !(lc = ncache_addr(Lf->id, Lf->na))
Packit Service 603f59
# else	/* !defined(NCACHE_NODEID) */
Packit Service 603f59
	||  !(lc = ncache_addr(Lf->na))
Packit Service 603f59
# endif	/* defined(NCACHE_NODEID) */
Packit Service 603f59
Packit Service 603f59
	) {
Packit Service 603f59
Packit Service 603f59
	/*
Packit Service 603f59
	 * If the node has no cache entry, see if it's the mount
Packit Service 603f59
	 * point of a known file system.
Packit Service 603f59
	 */
Packit Service 603f59
	    if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1)
Packit Service 603f59
		return((char *)NULL);
Packit Service 603f59
	    for (mtp = readmnt(); mtp; mtp = mtp->next) {
Packit Service 603f59
		if (!mtp->dir || !mtp->inode)
Packit Service 603f59
		    continue;
Packit Service 603f59
		if (Lf->dev == mtp->dev
Packit Service 603f59
		&&  mtp->inode == Lf->inode
Packit Service 603f59
		&&  strcmp(mtp->dir, Lf->fsdir) == 0)
Packit Service 603f59
		    return(cp);
Packit Service 603f59
	    }
Packit Service 603f59
	    return((char *)NULL);
Packit Service 603f59
	}
Packit Service 603f59
/*
Packit Service 603f59
 * Begin the path assembly.
Packit Service 603f59
 */
Packit Service 603f59
	if ((nl = lc->nl) > (blen - 1))
Packit Service 603f59
	    return((char *)NULL);
Packit Service 603f59
	cp = buf + blen - nl - 1;
Packit Service 603f59
	rlen = blen - nl - 1;
Packit Service 603f59
	(void) strcpy(cp, lc->nm);
Packit Service 603f59
/*
Packit Service 603f59
 * Look up the name cache entries that are parents of the node address.
Packit Service 603f59
 * Quit when:
Packit Service 603f59
 *
Packit Service 603f59
 *	there's no parent;
Packit Service 603f59
 *	the name is too large to fit in the receiving buffer.
Packit Service 603f59
 */
Packit Service 603f59
	for (;;) {
Packit Service 603f59
	    if (!lc->pa) {
Packit Service 603f59
		if (ncache_isroot(lc->dp, cp))
Packit Service 603f59
		    *fp = 1;
Packit Service 603f59
		break;
Packit Service 603f59
	    }
Packit Service 603f59
	    lc = lc->pa;
Packit Service 603f59
	    if (((nl = lc->nl) + 1) > rlen)
Packit Service 603f59
		break;
Packit Service 603f59
	    *(cp - 1) = '/';
Packit Service 603f59
	    cp--;
Packit Service 603f59
	    rlen--;
Packit Service 603f59
	    (void) strncpy((cp - nl), lc->nm, nl);
Packit Service 603f59
	    cp -= nl;
Packit Service 603f59
	    rlen -= nl;
Packit Service 603f59
	}
Packit Service 603f59
	return(cp);
Packit Service 603f59
}
Packit Service 603f59
#else	/* !defined(HASNCACHE) || !defined(USE_LIB_RNCH) */
Packit Service 603f59
char rnch_d1[] = "d"; char *rnch_d2 = rnch_d1;
Packit Service 603f59
#endif	/* defined(HASNCACHE) && defined(USE_LIB_RNCH) */