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