1/* 2 * rnch.c -- Sun format name cache functions for lsof library 3 */ 4 5 6/* 7 * Copyright 1997 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 33#include "../machine.h" 34 35#if defined(HASNCACHE) && defined(USE_LIB_RNCH) 36 37# if !defined(lint) 38static char copyright[] = 39"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; 40static char *rcsid = "$Id: rnch.c,v 1.11 2008/10/21 16:13:23 abe Exp $"; 41# endif /* !defined(lint) */ 42 43#include "../lsof.h" 44 45 46/* 47 * rnch.c - read Sun format (struct ncache) name cache 48 * 49 * This code is effective only when HASNCACHE is defined. 50 */ 51 52/* 53 * The caller must: 54 * 55 * #include the relevant header file -- e.g., <sys/dnlc.h>. 56 * 57 * Define X_NCSIZE as the nickname for the kernel cache size variable, 58 * or, if X_NCSIZE is undefined, define FIXED_NCSIZE as the size of the 59 * kernel cache. 60 * 61 * Define X_NCACHE as the nickname for the kernel cache address and 62 * define ADDR_NCACHE if the address is the address of the cache, 63 * rather than the address of a pointer to it. 64 * 65 * Define NCACHE_NXT if the kernel's name cache is a linked list, starting 66 * at the X_NCACHE address, rather than a table, starting at that address. 67 * 68 * Define any of the following casts that differ from their defaults: 69 * 70 * NCACHE_SZ_CAST cast for X_NCACHE (default int) 71 * 72 * The caller may: 73 * 74 * Define NCACHE_DP as the name of the element in the 75 * ncache structure that contains the 76 * parent vnode pointer. 77 * 78 * Default: dp 79 * 80 * Define NCACHE_NAME as the name of the element in the 81 * ncache structure that contains the 82 * name. 83 * 84 * Default: name 85 * 86 * Define NCACHE_NAMLEN as the name of the element in the 87 * ncache structure that contains the 88 * name length. 89 * 90 * Deafult: namlen 91 * 92 * Define NCACHE_NEGVN as the name of the name list element 93 * whose value is a vnode address to 94 * ignore when loading the kernel name 95 * cache. 96 * 97 * Define NCACHE_NODEID as the name of the element in the 98 * ncache structure that contains the 99 * vnode's capability ID. 100 * 101 * Define NCACHE_PARID as the name of the element in the 102 * ncache structure that contains the 103 * parent vnode's capability ID. 104 * 105 * Define NCACHE_VP as the name of the element in the 106 * ncache structure that contains the 107 * vnode pointer. 108 * 109 * Default: vp 110 * 111 * Note: if NCACHE_NODEID is defined, then NCACHE_PARID must be defined. 112 * 113 * 114 * The caller must: 115 * 116 * Define this prototype for ncache_load(): 117 * 118 * _PROTOTYPE(void ncache_load,(void)); 119 */ 120 121 122/* 123 * Local static values 124 */ 125 126static int Mch; /* name cache hash mask */ 127 128# if !defined(NCACHE_NC_CAST) 129#define NCACHE_SZ_CAST int 130# endif /* !defined(NCACHE_NC_CAST) */ 131 132static NCACHE_SZ_CAST Nc = 0; /* size of name cache */ 133static int Nch = 0; /* size of name cache hash pointer 134 * table */ 135struct l_nch { 136 KA_T vp; /* vnode address */ 137 KA_T dp; /* parent vnode address */ 138 struct l_nch *pa; /* parent Ncache address */ 139 140# if defined(NCACHE_NODEID) 141 unsigned long id; /* node's capability ID */ 142 unsigned long did; /* parent node's capability ID */ 143# endif /* defined(NCACHE_NODEID) */ 144 145 char *nm; /* name */ 146 int nl; /* name length */ 147}; 148 149static struct l_nch *Ncache = (struct l_nch *)NULL; 150 /* the local name cache */ 151static struct l_nch **Nchash = (struct l_nch **)NULL; 152 /* Ncache hash pointers */ 153static int Ncfirst = 1; /* first-call status */ 154 155# if defined(NCACHE_NEGVN) 156static KA_T NegVN = (KA_T)NULL; /* negative vnode address */ 157static int NegVNSt = 0; /* NegVN status: 0 = not loaded */ 158# endif /* defined(NCACHE_NEGVN) */ 159 160# if defined(NCACHE_NODEID) 161_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long i, KA_T v)); 162#define ncachehash(i,v) Nchash+(((((int)(v)>>2)+((int)(i)))*31415)&Mch) 163# else /* !defined(NCACHE_NODEID) */ 164_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T v)); 165#define ncachehash(v) Nchash+((((int)(v)>>2)*31415)&Mch) 166# endif /* defined(NCACHE_NODEID) */ 167 168_PROTOTYPE(static int ncache_isroot,(KA_T va, char *cp)); 169 170#define DEFNCACHESZ 1024 /* local size if X_NCSIZE kernel value < 1 */ 171#define LNCHINCRSZ 64 /* local size increment */ 172 173# if !defined(NCACHE_DP) 174#define NCACHE_DP dp 175# endif /* !defined(NCACHE_DP) */ 176 177# if !defined(NCACHE_NAME) 178#define NCACHE_NAME name 179# endif /* !defined(NCACHE_NAME) */ 180 181# if !defined(NCACHE_NAMLEN) 182#define NCACHE_NAMLEN namlen 183# endif /* !defined(NCACHE_NAMLEN) */ 184 185# if !defined(NCACHE_VP) 186#define NCACHE_VP vp 187# endif /* !defined(NCACHE_VP) */ 188 189 190/* 191 * ncache_addr() - look up a node's local ncache address 192 */ 193 194static struct l_nch * 195 196# if defined(NCACHE_NODEID) 197ncache_addr(i, v) 198# else /* !defined(NCACHE_NODEID) */ 199ncache_addr(v) 200# endif /* defined(NCACHE_NODEID) */ 201 202# if defined(NCACHE_NODEID) 203 unsigned long i; /* capability ID */ 204# endif /* defined(NCACHE_NODEID) */ 205 206 KA_T v; /* vnode's address */ 207{ 208 struct l_nch **hp; 209 210# if defined(NCACHE_NODEID) 211 for (hp = ncachehash(i, v); *hp; hp++) 212# else /* !defined(NCACHE_NODEID) */ 213 for (hp = ncachehash(v); *hp; hp++) 214# endif /* defined(NCACHE_NODEID) */ 215 216 { 217 218# if defined(NCACHE_NODEID) 219 if ((*hp)->vp == v && (*hp)->id == i) 220# else /* !defined(NCACHE_NODEID) */ 221 if ((*hp)->vp == v) 222# endif /* defined(NCACHE_NODEID) */ 223 224 return(*hp); 225 } 226 return((struct l_nch *)NULL); 227} 228 229 230/* 231 * ncache_isroot() - is head of name cache path a file system root? 232 */ 233 234static int 235ncache_isroot(va, cp) 236 KA_T va; /* kernel vnode address */ 237 char *cp; /* partial path */ 238{ 239 char buf[MAXPATHLEN]; 240 int i; 241 MALLOC_S len; 242 struct mounts *mtp; 243 struct stat sb; 244 struct vnode v; 245 static int vca = 0; 246 static int vcn = 0; 247 static KA_T *vc = (KA_T *)NULL; 248 249 if (!va) 250 return(0); 251/* 252 * Search the root vnode cache. 253 */ 254 for (i = 0; i < vcn; i++) { 255 if (va == vc[i]) 256 return(1); 257 } 258/* 259 * Read the vnode and see if it's a VDIR node with the VROOT flag set. If 260 * it is, then the path is complete. 261 * 262 * If it isn't, and if the file has an inode number, search the mount table 263 * and see if the file system's inode number is known. If it is, form the 264 * possible full path, safely stat() it, and see if it's inode number matches 265 * the one we have for this file. If it does, then the path is complete. 266 */ 267 if (kread((KA_T)va, (char *)&v, sizeof(v)) 268 || v.v_type != VDIR || !(v.v_flag & VROOT)) { 269 270 /* 271 * The vnode tests failed. Try the inode tests. 272 */ 273 if (Lf->inp_ty != 1 || !Lf->inode 274 || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1) 275 return(0); 276 if ((len + 1 + strlen(cp) + 1) > sizeof(buf)) 277 return(0); 278 for (mtp = readmnt(); mtp; mtp = mtp->next) { 279 if (!mtp->dir || !mtp->inode) 280 continue; 281 if (strcmp(Lf->fsdir, mtp->dir) == 0) 282 break; 283 } 284 if (!mtp) 285 return(0); 286 (void) strcpy(buf, Lf->fsdir); 287 if (buf[len - 1] != '/') 288 buf[len++] = '/'; 289 (void) strcpy(&buf[len], cp); 290 if (statsafely(buf, &sb) != 0 291 || (unsigned long)sb.st_ino != Lf->inode) 292 return(0); 293 } 294/* 295 * Add the vnode address to the root vnode cache. 296 */ 297 if (vcn >= vca) { 298 vca += 10; 299 len = (MALLOC_S)(vca * sizeof(KA_T)); 300 if (!vc) 301 vc = (KA_T *)malloc(len); 302 else 303 vc = (KA_T *)realloc(vc, len); 304 if (!vc) { 305 (void) fprintf(stderr, "%s: no space for root vnode table\n", 306 Pn); 307 Exit(1); 308 } 309 } 310 vc[vcn++] = va; 311 return(1); 312} 313 314 315/* 316 * ncache_load() - load the kernel's name cache 317 */ 318 319void 320ncache_load() 321{ 322 char *cp, *np; 323 struct l_nch **hp, *lc; 324 int i, len, n; 325 static int iNc = 0; 326 struct ncache *kc; 327 static KA_T kp = (KA_T)NULL; 328 KA_T v; 329 330# if defined(HASDNLCPTR) 331 static int na = 0; 332 static char *nb = (char *)NULL; 333# endif /* defined(HASDNLCPTR) */ 334 335# if defined(NCACHE_NXT) 336 static KA_T kf; 337 struct ncache nc; 338# else /* !defined(NCACHE_NXT) */ 339 static struct ncache *kca = (struct ncache *)NULL; 340# endif /* defined(NCACHE_NXT) */ 341 342 if (!Fncache) 343 return; 344 if (Ncfirst) { 345 346 /* 347 * Do startup (first-time) functions. 348 */ 349 Ncfirst = 0; 350 /* 351 * Establish kernel cache size. 352 */ 353 354# if defined(X_NCSIZE) 355 v = (KA_T)0; 356 if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 357 || !v 358 || kread((KA_T)v, (char *)&Nc, sizeof(Nc))) 359 { 360 if (!Fwarn) 361 (void) fprintf(stderr, 362 "%s: WARNING: can't read name cache size: %s\n", 363 Pn, print_kptr(v, (char *)NULL, 0)); 364 iNc = Nc = 0; 365 return; 366 } 367 iNc = Nc; 368# else /* !defined(X_NCSIZE) */ 369 iNc = Nc = FIXED_NCSIZE; 370# endif /* defined(X_NCSIZE) */ 371 372 if (Nc < 1) { 373 if (!Fwarn) { 374 (void) fprintf(stderr, 375 "%s: WARNING: kernel name cache size: %d\n", Pn, Nc); 376 (void) fprintf(stderr, 377 " Cache size assumed to be: %d\n", DEFNCACHESZ); 378 } 379 iNc = Nc = DEFNCACHESZ; 380 } 381 382# if defined(NCACHE_NEGVN) 383 /* 384 * Get negative vnode address. 385 */ 386 if (!NegVNSt) { 387 if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN) 388 < 0) 389 NegVN = (KA_T)NULL; 390 NegVNSt = 1; 391 } 392# endif /* defined(NCACHE_NEGVN) */ 393 394 /* 395 * Establish kernel cache address. 396 */ 397 398# if defined(ADDR_NCACHE) 399 kp = (KA_T)0; 400 if (get_Nl_value(X_NCACHE,(struct drive_Nl *)NULL,(KA_T *)&kp) < 0 401 || !kp) { 402 if (!Fwarn) 403 (void) fprintf(stderr, 404 "%s: WARNING: no name cache address\n", Pn); 405 iNc = Nc = 0; 406 return; 407 } 408# else /* !defined(ADDR_NCACHE) */ 409 v = (KA_T)0; 410 if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0 411 || !v 412 || kread((KA_T)v, (char *)&kp, sizeof(kp))) { 413 if (!Fwarn) 414 (void) fprintf(stderr, 415 "%s: WARNING: can't read name cache ptr: %s\n", 416 Pn, print_kptr(v, (char *)NULL, 0)); 417 iNc = Nc = 0; 418 return; 419 } 420# endif /* defined(ADDR_NCACHE) */ 421 422 /* 423 * Allocate space for a local copy of the kernel's cache. 424 */ 425 426# if !defined(NCACHE_NXT) 427 len = Nc * sizeof(struct ncache); 428 if (!(kca = (struct ncache *)malloc((MALLOC_S)len))) { 429 if (!Fwarn) 430 (void) fprintf(stderr, 431 "%s: can't allocate name cache space: %d\n", Pn, len); 432 Exit(1); 433 } 434# endif /* !defined(NCACHE_NXT) */ 435 436 /* 437 * Allocate space for the local cache. 438 */ 439 len = Nc * sizeof(struct l_nch); 440 if (!(Ncache = (struct l_nch *)calloc(Nc, sizeof(struct l_nch)))) { 441 442no_local_space: 443 444 if (!Fwarn) 445 (void) fprintf(stderr, 446 "%s: no space for %d byte local name cache\n", Pn, len); 447 Exit(1); 448 } 449 } else { 450 451 /* 452 * Do setup for repeat calls. 453 */ 454 if (!iNc) 455 return; 456 if (Nchash) { 457 (void) free((FREE_P *)Nchash); 458 Nchash = (struct l_nch **)NULL; 459 } 460 if (Ncache) { 461 462 /* 463 * Free space malloc'd to names in local name cache. 464 */ 465 for (i = 0, lc = Ncache; i < Nc; i++, lc++) { 466 if (lc->nm) { 467 (void) free((FREE_P *)lc->nm); 468 lc->nm = (char *)NULL; 469 } 470 } 471 } 472 Nc = iNc; 473 474# if defined(NCACHE_NXT) 475 kp = kf; 476# endif /* defined(NCACHE_NXT) */ 477 478 } 479 480# if !defined(NCACHE_NXT) 481 482/* 483 * Read the kernel's name cache. 484 */ 485 if (kread(kp, (char *)kca, (Nc * sizeof(struct ncache)))) { 486 if (!Fwarn) 487 (void) fprintf(stderr, 488 "%s: WARNING: can't read kernel's name cache: %s\n", 489 Pn, print_kptr(kp, (char *)NULL, 0)); 490 Nc = 0; 491 return; 492 } 493# endif /* !defined(NCACHE_NXT) */ 494 495/* 496 * Build a local copy of the kernel name cache. 497 */ 498 499# if defined(NCACHE_NXT) 500 for (i = iNc * 16, kc = &nc, kf = kp, lc = Ncache, n = 0; kp; ) 501# else /* !defined(NCACHE_NXT) */ 502 for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++) 503# endif /* defined(NCACHE_NXT) */ 504 505 { 506 507# if defined(NCACHE_NXT) 508 if (kread(kp, (char *)kc, sizeof(nc))) 509 break; 510 if ((kp = (KA_T)kc->NCACHE_NXT) == kf) 511 kp = (KA_T)NULL; 512# endif /* defined(NCACHE_NXT) */ 513 514 if (!kc->NCACHE_VP || (len = kc->NCACHE_NAMLEN) < 1) 515 continue; 516 517# if defined(NCACHE_NEGVN) 518 if (NegVN && ((KA_T)kc->NCACHE_VP == NegVN)) 519 continue; 520# endif /* defined(NCACHE_NEGVN) */ 521 522# if defined(HASDNLCPTR) 523 /* 524 * Read name from kernel to a temporary buffer. 525 */ 526 if (len > na) { 527 na = len; 528 if (!nb) 529 nb = (char *)malloc(na); 530 else 531 nb = (char *)realloc((MALLOC_P *)nb, na); 532 if (!nb) { 533 (void) fprintf(stderr, 534 "%s: can't allocate %d byte temporary name buffer\n", 535 Pn, na); 536 Exit(1); 537 } 538 } 539 if (!kc->NCACHE_NAME || kread((KA_T)kc->NCACHE_NAME, nb, len)) 540 continue; 541 np = nb; 542# else /* !defined(HASDNLCPTR) */ 543 /* 544 * Use name that is in the kernel cache entry. 545 */ 546 if (len > NC_NAMLEN) 547 continue; 548 np = kc->NCACHE_NAME; 549# endif /* defined(HASDNLCPTR) */ 550 551 if (len < 3 && *np == '.') { 552 if (len == 1 || (len == 2 && np[1] == '.')) 553 continue; 554 } 555 /* 556 * Allocate space for name in local cache entry. 557 */ 558 if (!(cp = (char *)malloc(len + 1))) { 559 (void) fprintf(stderr, 560 "%s: can't allocate %d bytes for name cache name: %s\n", 561 Pn, len + 1, np); 562 Exit(1); 563 } 564 (void) strncpy(cp, np, len); 565 cp[len] = '\0'; 566 567# if defined(NCACHE_NXT) 568 if (n >= Nc) { 569 570 /* 571 * Allocate more local space to receive the kernel's linked 572 * entries. 573 */ 574 Nc += LNCHINCRSZ; 575 if (!(Ncache = (struct l_nch *)realloc(Ncache, 576 (MALLOC_S)(Nc * sizeof(struct l_nch))))) 577 { 578 (void) fprintf(stderr, 579 "%s: no more space for %d entry local name cache\n", 580 Pn, Nc); 581 Exit(1); 582 } 583 lc = &Ncache[n]; 584 iNc = Nc; 585 } 586# endif /* defined(NCACHE_NXT) */ 587 588 /* 589 * Complete the local cache entry. 590 */ 591 lc->vp = (KA_T)kc->NCACHE_VP; 592 lc->dp = (KA_T)kc->NCACHE_DP; 593 lc->pa = (struct l_nch *)NULL; 594 lc->nm = cp; 595 lc->nl = len; 596 597# if defined(NCACHE_NODEID) 598 lc->id = (unsigned long)kc->NCACHE_NODEID; 599 lc->did = (unsigned long)kc->NCACHE_PARID; 600# endif /* defined(NCACHE_NODEID) */ 601 602 n++; 603 lc++; 604 605# if defined(NCACHE_NXT) 606 if (n >= i) { 607 if (!Fwarn) 608 (void) fprintf(stderr, 609 "%s: WARNING: name cache truncated at %d entries\n", 610 Pn, n); 611 break; 612 } 613# endif /* defined(NCACHE_NXT) */ 614 615 } 616/* 617 * Reduce memory usage, as required. 618 */ 619 620# if !defined(NCACHE_NXT) 621 if (!RptTm) 622 (void) free((FREE_P *)kca); 623# endif /* !defined(NCACHE_NXT) */ 624 625 if (n < 1) { 626 if (!RptTm && Ncache) { 627 628 /* 629 * If not in repeat mode, free the space that has been malloc'd 630 * to the local name cache. 631 */ 632 for (i = 0, lc = Ncache; i < Nc; i++, lc++) { 633 if (lc->nm) { 634 (void) free((FREE_P *)lc->nm); 635 lc->nm = (char *)NULL; 636 } 637 } 638 (void) free((FREE_P *)Ncache); 639 Ncache = (struct l_nch *)NULL; 640 Nc = 0; 641 } 642 if (!Fwarn) 643 (void) fprintf(stderr, 644 "%s: WARNING: unusable name cache size: %d\n", Pn, n); 645 return; 646 } 647 if (n < Nc) { 648 Nc = n; 649 if (!RptTm) { 650 len = Nc * sizeof(struct l_nch); 651 if (!(Ncache = (struct l_nch *)realloc(Ncache, len))) 652 goto no_local_space; 653 } 654 } 655/* 656 * Build a hash table to locate Ncache entries. 657 */ 658 for (Nch = 1; Nch < Nc; Nch <<= 1) 659 ; 660 Nch <<= 1; 661 Mch = Nch - 1; 662 if (!(Nchash = (struct l_nch **)calloc(Nch+Nc, sizeof(struct l_nch *)))) 663 { 664 if (!Fwarn) 665 (void) fprintf(stderr, 666 "%s: no space for %d name cache hash pointers\n", 667 Pn, Nch + Nc); 668 Exit(1); 669 } 670 for (i = 0, lc = Ncache; i < Nc; i++, lc++) { 671 672# if defined(NCACHE_NODEID) 673 for (hp = ncachehash(lc->id, lc->vp), n = 1; *hp; hp++) 674# else /* !defined(NCACHE_NODEID) */ 675 for (hp = ncachehash(lc->vp), n = 1; *hp; hp++) 676# endif /* defined(NCACHE_NODEID) */ 677 678 { 679 if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0 680 && (*hp)->dp == lc->dp 681 682# if defined(NCACHE_NODEID) 683 && (*hp)->id == lc->id && (*hp)->did == lc->did 684# endif /* defined(NCACHE_NODEID) */ 685 686 ) { 687 n = 0; 688 break; 689 } 690 } 691 if (n) 692 *hp = lc; 693 } 694/* 695 * Make a final pass through the local cache and convert parent vnode 696 * addresses to local name cache pointers. 697 */ 698 for (i = 0, lc = Ncache; i < Nc; i++, lc++) { 699 if (!lc->dp) 700 continue; 701 702# if defined(NCACHE_NEGVN) 703 if (NegVN && (lc->dp == NegVN)) { 704 lc->pa = (struct l_nch *)NULL; 705 continue; 706 } 707# endif /* defined(NCACHE_NEGVN) */ 708 709# if defined(NCACHE_NODEID) 710 lc->pa = ncache_addr(lc->did, lc->dp); 711# else /* !defined(NCACHE_NODEID) */ 712 lc->pa = ncache_addr(lc->dp); 713# endif /* defined(NCACHE_NODEID) */ 714 715 } 716} 717 718 719/* 720 * ncache_lookup() - look up a node's name in the kernel's name cache 721 */ 722 723char * 724ncache_lookup(buf, blen, fp) 725 char *buf; /* receiving name buffer */ 726 int blen; /* receiving buffer length */ 727 int *fp; /* full path reply */ 728{ 729 char *cp = buf; 730 struct l_nch *lc; 731 struct mounts *mtp; 732 int nl, rlen; 733 734 *cp = '\0'; 735 *fp = 0; 736 737# if defined(HASFSINO) 738/* 739 * If the entry has an inode number that matches the inode number of the 740 * file system mount point, return an empty path reply. That tells the 741 * caller to print the file system mount point name only. 742 */ 743 if ((Lf->inp_ty == 1) && Lf->fs_ino && (Lf->inode == Lf->fs_ino)) 744 return(cp); 745# endif /* defined(HASFSINO) */ 746 747/* 748 * Look up the name cache entry for the node address. 749 */ 750 if (!Nc 751 752# if defined(NCACHE_NODEID) 753 || !(lc = ncache_addr(Lf->id, Lf->na)) 754# else /* !defined(NCACHE_NODEID) */ 755 || !(lc = ncache_addr(Lf->na)) 756# endif /* defined(NCACHE_NODEID) */ 757 758 ) { 759 760 /* 761 * If the node has no cache entry, see if it's the mount 762 * point of a known file system. 763 */ 764 if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1) 765 return((char *)NULL); 766 for (mtp = readmnt(); mtp; mtp = mtp->next) { 767 if (!mtp->dir || !mtp->inode) 768 continue; 769 if (Lf->dev == mtp->dev 770 && mtp->inode == Lf->inode 771 && strcmp(mtp->dir, Lf->fsdir) == 0) 772 return(cp); 773 } 774 return((char *)NULL); 775 } 776/* 777 * Begin the path assembly. 778 */ 779 if ((nl = lc->nl) > (blen - 1)) 780 return((char *)NULL); 781 cp = buf + blen - nl - 1; 782 rlen = blen - nl - 1; 783 (void) strcpy(cp, lc->nm); 784/* 785 * Look up the name cache entries that are parents of the node address. 786 * Quit when: 787 * 788 * there's no parent; 789 * the name is too large to fit in the receiving buffer. 790 */ 791 for (;;) { 792 if (!lc->pa) { 793 if (ncache_isroot(lc->dp, cp)) 794 *fp = 1; 795 break; 796 } 797 lc = lc->pa; 798 if (((nl = lc->nl) + 1) > rlen) 799 break; 800 *(cp - 1) = '/'; 801 cp--; 802 rlen--; 803 (void) strncpy((cp - nl), lc->nm, nl); 804 cp -= nl; 805 rlen -= nl; 806 } 807 return(cp); 808} 809#else /* !defined(HASNCACHE) || !defined(USE_LIB_RNCH) */ 810char rnch_d1[] = "d"; char *rnch_d2 = rnch_d1; 811#endif /* defined(HASNCACHE) && defined(USE_LIB_RNCH) */ 812