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