| /* |
| * dnode.c - DEC OSF/1, Digital UNIX, Tru64 UNIX node functions for lsof |
| */ |
| |
| |
| /* |
| * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana |
| * 47907. All rights reserved. |
| * |
| * Written by Victor A. Abell |
| * |
| * This software is not subject to any license of the American Telephone |
| * and Telegraph Company or the Regents of the University of California. |
| * |
| * Permission is granted to anyone to use this software for any purpose on |
| * any computer system, and to alter it and redistribute it freely, subject |
| * to the following restrictions: |
| * |
| * 1. Neither the authors nor Purdue University are responsible for any |
| * consequences of the use of this software. |
| * |
| * 2. The origin of this software must not be misrepresented, either by |
| * explicit claim or by omission. Credit to the authors and Purdue |
| * University must appear in documentation and sources. |
| * |
| * 3. Altered versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software. |
| * |
| * 4. This notice may not be removed or altered. |
| */ |
| |
| #ifndef lint |
| static char copyright[] = |
| "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; |
| static char *rcsid = "$Id: dnode.c,v 1.23 2006/03/27 20:40:59 abe Exp $"; |
| #endif |
| |
| |
| #include "lsof.h" |
| |
| |
| /* |
| * Local definitions |
| */ |
| |
| #if ADVFSV>=500 |
| /* |
| * AdvFS (MSFS) definitions for AdvFS version 5.0 and above. |
| */ |
| |
| struct fs_stat { /* file system stat(2) info structure |
| * for AdvFS 5.0 and above */ |
| unsigned int num; /* node number */ |
| unsigned int d1; |
| mode_t d2; |
| uid_t d3; |
| gid_t d4; |
| dev_t rdev; /* character or block device number */ |
| off_t size; /* file size */ |
| |
| # if defined(__arch32__) |
| unsigned int d5; |
| # endif /* defined(__arch32__) */ |
| |
| time_t d6; |
| int d7; |
| time_t d8; |
| int d9; |
| time_t d10; |
| int d11; |
| unsigned int d12[5]; |
| unsigned short nlink; /* link count */ |
| }; |
| |
| struct fsContext { /* file system context for AdvFS 5.0 |
| * and above */ |
| short d1[2]; |
| unsigned int d2[2]; |
| long d3; |
| int d4[2]; |
| lock_data_t d5; |
| long d6; |
| simple_lock_data_t d7; |
| unsigned int d8[2]; |
| long d9; |
| struct fs_stat st; /* file stats */ |
| }; |
| |
| struct advfsnode { /* AdvFS (MSFS) node definition for |
| * AdvFS 5.0 and above */ |
| unsigned long d1; |
| struct fsContext *a_con; /* context pointer */ |
| }; |
| #endif /* ADVFSV>=500 */ |
| |
| #if DUV>=50000 |
| typedef struct cnode { /* CFS node structure definition for |
| * Tru64 UNIX 5.0 and above */ |
| udecl_simple_lock_data(, d1) |
| unsigned int d2; |
| time_t d3; |
| unsigned long d4[3]; |
| |
| # if DUV<50100 |
| int d5[2]; |
| off_t d6; |
| # endif /* DUV<50100 */ |
| |
| unsigned long d7; |
| vattr_t c_attr; /* 96:Cached vnode attributes */ |
| } cnode_t; |
| #endif /* DUV>=50000 */ |
| |
| struct l_lock { /* local lock info */ |
| struct eflock set; /* lock data */ |
| struct l_lock *next; |
| }; |
| |
| struct l_flinfo { /* local file lock info */ |
| struct vnode *vp; /* identity of locked vnode */ |
| struct l_lock *lp; /* lock information */ |
| struct l_flinfo *next; |
| }; |
| |
| #define L_FLINFO_HSZ 256 /* local file lock information hash |
| * table size (must be a power of 2) */ |
| #define L_FLINFO_HASH(va) (((int)((long)(va) * 31415L) >> 5) & (L_FLINFO_HSZ - 1)) |
| |
| |
| /* |
| * Local static variables |
| */ |
| |
| static struct l_flinfo **Flinfo = (struct l_flinfo **)NULL; |
| /* local file lock hash buckets */ |
| static int FlinfoSt = 0; /* Flinfo[] load status */ |
| |
| |
| /* |
| * Local function prototypes |
| */ |
| |
| _PROTOTYPE(static char isvlocked,(struct vnode *vp)); |
| _PROTOTYPE(static int load_flinfo,(void)); |
| _PROTOTYPE(static int readvnode,(KA_T va, struct vnode *v)); |
| _PROTOTYPE(static void get_proc_sz,(struct procnode *pn)); |
| |
| |
| /* |
| * clr_flinfo() - clear local file lock table information |
| */ |
| |
| void |
| clr_flinfo() |
| { |
| struct l_lock *lf, *lfn; |
| int i; |
| struct l_flinfo *fi, *fin; |
| |
| if (!Flinfo && !FlinfoSt) |
| return; |
| for (i = 0; i < L_FLINFO_HSZ; i++) { |
| if (!(fi = Flinfo[i])) |
| continue; |
| do { |
| if ((lf = fi->lp)) { |
| do { |
| lfn = lf->next; |
| (void) free((FREE_P *)lf); |
| } while ((lf = lfn)); |
| } |
| fin = fi->next; |
| (void) free((FREE_P *)fi); |
| } while ((fi = fin)); |
| Flinfo[i] = (struct l_flinfo *)NULL; |
| } |
| FlinfoSt = 0; |
| } |
| |
| |
| /* |
| * get_proc_sz() - get size of /proc file system file |
| */ |
| |
| static void |
| get_proc_sz(pn) |
| struct procnode *pn; /* pointer to procnode */ |
| { |
| struct vm_map m; |
| struct proc *p; |
| KA_T pa; |
| int px; |
| struct task t; |
| /* |
| * Search for procnode's process by PID. |
| */ |
| for (p = Ps, px = 0; px < Psn; p++, px++) { |
| if (p->p_pid == pn->prc_pid) |
| break; |
| } |
| if (px >= Psn) |
| return; |
| /* |
| * Get the task structure address, then read the task structure. Set |
| * the procnode's file size from the memory map information in the task |
| * structure. |
| */ |
| |
| # if DUV<30000 |
| if (!(pa = (KA_T)p->task)) |
| return; |
| # else /* DUV>=30000 */ |
| if (!(pa = Pa[px])) |
| return; |
| pa = (KA_T)((char *)pa - sizeof(t)); |
| # endif /* DUV<30000 */ |
| |
| if (kread(pa, (char *)&t, sizeof(t))) |
| return; |
| if (!t.map || kread((KA_T)t.map, (char *)&m, sizeof(m))) |
| return; |
| Lf->sz = (SZOFFTYPE)m.vm_size; |
| Lf->sz_def = 1; |
| } |
| |
| |
| /* |
| * isvlocked() - is vnode locked? |
| */ |
| |
| static char |
| isvlocked(vp) |
| struct vnode *vp; /* vnode's kernel address */ |
| { |
| struct l_flinfo *fp; |
| int i, l; |
| struct l_lock *lp; |
| |
| if (!Flinfo || !FlinfoSt) { |
| if (!load_flinfo()) |
| return(' '); |
| } |
| /* |
| * Hash the vnode address and see if there's a local file lock information |
| * structure for it. |
| */ |
| i = L_FLINFO_HASH(vp); |
| for (fp = Flinfo[i]; fp; fp = fp->next) { |
| if (fp->vp == vp) |
| break; |
| } |
| if (!fp) |
| return(' '); |
| /* |
| * Search the vnode's lock list for one held by this process. |
| */ |
| for (lp = fp->lp; lp; lp = lp->next) { |
| if (lp->set.l_rsys || lp->set.l_pid != (pid_t)Lp->pid) |
| continue; |
| if (lp->set.l_whence == 0 && lp->set.l_start == 0 |
| && ((lp->set.l_len == 0x8000000000000000) |
| || (lp->set.l_len == 0x7fffffffffffffff))) |
| l = 1; |
| else |
| l = 0; |
| if (lp->set.l_type == F_WRLCK) |
| return(l ? 'W' : 'w'); |
| else if (lp->set.l_type == F_RDLCK) |
| return(l ? 'R' : 'r'); |
| return(' '); |
| } |
| return(' '); |
| } |
| |
| |
| /* |
| * load_flinfo() - load local file lock information |
| */ |
| |
| static int |
| load_flinfo() |
| { |
| struct flino fi; |
| struct filock fl; |
| KA_T fif, fip, flf, flp; |
| int i; |
| struct l_flinfo *lfi; |
| struct l_lock *ll; |
| KA_T v; |
| |
| if (Flinfo && FlinfoSt) |
| return(1); |
| /* |
| * Get kernel fids chain pointer. |
| */ |
| if (get_Nl_value("fids", Drive_Nl, &v) < 0 || !v |
| || kread((KA_T)v, (char *)&fip, sizeof(fip))) |
| return(0); |
| /* |
| * Define local hash buckets, if necessary. |
| */ |
| if (!Flinfo) { |
| if (!(Flinfo = (struct l_flinfo **)calloc(sizeof(struct flinfo *), |
| L_FLINFO_HSZ))) |
| { |
| (void) fprintf(stderr, |
| "%s: can't allocate %d byte local lock hash buckets\n", |
| Pn, L_FLINFO_HSZ * sizeof(struct l_flinfo *)); |
| Exit(1); |
| } |
| } |
| /* |
| * Follow the fids chain. |
| */ |
| if (!(fif = fip)) |
| return(1); |
| /* |
| * Follow the filock chain for this fid entry. |
| * Duplicate it via the lock file lock information hash buckets. |
| */ |
| do { |
| if (kread(fip, (char *)&fi, sizeof(fi))) |
| return(0); |
| if (!(flf = (KA_T)fi.fl_flck)) |
| continue; |
| /* |
| * Allocate a local file lock information structure for this fid. |
| */ |
| if (!(lfi = (struct l_flinfo *)malloc(sizeof(struct l_flinfo)))) { |
| (void) fprintf(stderr, |
| "%s: no space for local vnode lock info struct\n", Pn); |
| Exit(1); |
| } |
| lfi->vp = fi.vp; |
| lfi->lp = (struct l_lock *)NULL; |
| lfi->next = (struct l_flinfo *)NULL; |
| /* |
| * Follow the flino's filock chain, duplicating it locally. |
| */ |
| flp = flf; |
| do { |
| if (kread(flp, (char *)&fl, sizeof(fl))) |
| break; |
| /* |
| * Allocate a local lock information structure and link it |
| * to the chain for its vnode. |
| */ |
| if (!(ll = (struct l_lock *)malloc(sizeof(struct l_lock)))) { |
| (void) fprintf(stderr, |
| "%s: no space for local lock struct\n", Pn); |
| Exit(1); |
| } |
| ll->next = lfi->lp; |
| lfi->lp = ll; |
| ll->set = fl.set; |
| } while ((flp = (KA_T)fl.next) && flp != flf); |
| /* |
| * Link the file lock information structure to its hash bucket. |
| */ |
| i = L_FLINFO_HASH(lfi->vp); |
| lfi->next = Flinfo[i]; |
| Flinfo[i] = lfi; |
| } while ((fip = (KA_T)fi.next) && fip != fif); |
| FlinfoSt = 1; |
| return(1); |
| } |
| |
| |
| /* |
| * process_node() - process vnode |
| */ |
| |
| void |
| process_node(va) |
| KA_T va; /* vnode kernel space address */ |
| { |
| struct advfsnode *a = (struct advfsnode *)NULL; |
| struct cdnode *c = (struct cdnode *)NULL; |
| dev_t dev, rdev; |
| unsigned char devs = 0; |
| unsigned char rdevs = 0; |
| struct inode *i = (struct inode *)NULL; |
| struct mfsnode *m = (struct mfsnode *)NULL; |
| struct procnode *p = (struct procnode *)NULL; |
| struct procfsid *pfi; |
| struct rnode *r = (struct rnode *)NULL; |
| struct spec_node *s = (struct spec_node *)NULL; |
| struct spec_node sn; |
| struct s5inode *s5 = (struct s5inode *)NULL; |
| char *ty; |
| enum vtype type; |
| unsigned long ul; |
| static struct vnode *v = (struct vnode *)NULL; |
| struct l_vfs *vfs; |
| |
| #if DUV>=30000 |
| struct fifonode *f = (struct fifonode *)NULL; |
| struct fifonode fn; |
| static struct vnode *fv = (struct vnode *)NULL; |
| #endif /* DUV>=30000 */ |
| |
| #if DUV>=50000 |
| cnode_t *cn = (cnode_t *)NULL; |
| struct fsContext fsc; |
| int fscs = 0; |
| #endif /* DUV>=50000 */ |
| |
| /* |
| * Read the vnode. |
| */ |
| if (!va) { |
| enter_nm("no vnode address"); |
| return; |
| } |
| if (!v) { |
| |
| /* |
| * Allocate space for the Digital UNIX vnode. |
| */ |
| if (!(v = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) { |
| (void) fprintf(stderr, "%s: no space for vnode buffer\n", Pn); |
| Exit(1); |
| } |
| |
| #if DUV>=30000 |
| if (!(fv = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) { |
| (void) fprintf(stderr, "%s: no space for fvnode buffer\n", Pn); |
| Exit(1); |
| } |
| #endif /* DUV>=30000 */ |
| |
| } |
| if (readvnode(va, v)) { |
| enter_nm(Namech); |
| return; |
| } |
| |
| #if defined(HASNCACHE) |
| Lf->na = va; |
| # if defined(HASNCVPID) |
| Lf->id = (unsigned long)v->v_id; |
| # endif /* defined(HASNCVPID) */ |
| #endif /* defined(HASNCACHE) */ |
| |
| #if defined(HASFSTRUCT) |
| Lf->fsv |= FSV_NI; |
| Lf->fna = va; |
| #endif /* defined(HASFSTRUCT) */ |
| |
| /* |
| * Get the mount structure and determine the vnode type. |
| */ |
| if (!v->v_mount) |
| vfs = (struct l_vfs *)NULL; |
| else |
| vfs = readvfs((KA_T)v->v_mount); |
| if (vfs) { |
| switch (vfs->type) { |
| case MOUNT_NFS: |
| |
| #if defined(MOUNT_NFS3) |
| case MOUNT_NFS3: |
| #endif /* defined(MOUNT_NFS3) */ |
| |
| Ntype = N_NFS; |
| break; |
| } |
| if (Ntype == N_REGLR) { |
| switch (v->v_type) { |
| case VFIFO: |
| Ntype = N_FIFO; |
| break; |
| } |
| } |
| } |
| /* |
| * Determine the lock type. |
| */ |
| if (FILEPTR && (FILEPTR->f_flag & FSHLOCK)) |
| Lf->lock = 'R'; |
| else if (FILEPTR && (FILEPTR->f_flag & FEXLOCK)) |
| Lf->lock = 'W'; |
| else |
| Lf->lock = isvlocked((struct vnode *)va); |
| /* |
| * Define the specific Digital UNIX node pointer. |
| */ |
| |
| #if DUV>=30000 |
| if (Ntype == N_FIFO) { |
| if (v->v_fifonode |
| && !kread((KA_T)v->v_fifonode, (char *)&fn, sizeof(fn))) |
| f = &fn; |
| } |
| #endif /* DUV>=30000 */ |
| |
| switch (v->v_tag) { |
| case VT_CDFS: |
| c = (struct cdnode *)v->v_data; |
| break; |
| |
| #if DUV>=50000 |
| case VT_CFS: |
| cn = (cnode_t *)v->v_data; |
| break; |
| #endif /* DUV>=50000 */ |
| |
| case VT_MFS: |
| m = (struct mfsnode *)v->v_data; |
| break; |
| case VT_NFS: |
| r = (struct rnode *)v->v_data; |
| break; |
| case VT_NON: |
| |
| #if DUV<20000 |
| if (v->v_specinfo |
| && !kread((KA_T)v->v_specinfo, (char *)&sn, sizeof(sn))) |
| s = &sn; |
| else |
| #else /* DUV>=20000 */ |
| # if DUV>=30000 |
| if (!f) |
| # endif /* DUV>=30000 */ |
| #endif /* DUV<20000 */ |
| |
| s = (struct spec_node *)v->v_data; |
| break; |
| case VT_PRFS: |
| p = (struct procnode *)v->v_data; |
| break; |
| case VT_S5FS: |
| s5 = (struct s5inode *)v->v_data; |
| break; |
| case VT_MSFS: |
| a = (struct advfsnode *)v->v_data; |
| |
| #if ADVFSV>=500 |
| if (a->a_con |
| && !kread((KA_T)a->a_con, (char *)&fsc, sizeof(fsc))) |
| fscs = 1; |
| #endif /* ADVFSV>=500 */ |
| |
| break; |
| case VT_UFS: |
| i = (struct inode *)v->v_data; |
| break; |
| default: |
| (void) snpf(Namech, Namechl, "unknown node type, v_tag=%d", |
| v->v_tag); |
| enter_nm(Namech); |
| return; |
| } |
| /* |
| * Get device and type for printing. |
| */ |
| type = v->v_type; |
| if (a) { |
| if (vfs && vfs->dev) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| if ((type == VCHR) || (type == VBLK)) { |
| |
| #if ADVFSV>=500 |
| if (fscs) { |
| rdev = fsc.st.rdev; |
| rdevs = 1; |
| } |
| #else /* ADVFSV<500 */ |
| rdev = a->a_rdev; |
| rdevs = 1; |
| #endif /* ADVFSV>=500 */ |
| |
| } |
| } else if (c) { |
| dev = c->cd_dev; |
| devs = 1; |
| } |
| |
| #if DUV>=50000 |
| else if (cn) { |
| if (vfs && vfs->dev) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| if ((type == VCHR) || (type == VBLK)) { |
| if (cn->c_attr.va_mask & AT_RDEV) { |
| rdev = cn->c_attr.va_rdev; |
| rdevs = 1; |
| } |
| } |
| } |
| #endif /* DUV>=50000 */ |
| |
| else if (i) { |
| if (i->i_dev) { |
| dev = i->i_dev; |
| devs = 1; |
| } else if (vfs && vfs->dev) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| if ((type == VCHR) || (type == VBLK)) { |
| rdev = i->i_din.di_db[0]; |
| rdevs = 1; |
| } |
| } else if (r) { |
| dev = r->r_attr.va_fsid; |
| devs = 1; |
| if ((type == VCHR) || (type == VBLK)) { |
| rdev = r->r_attr.va_rdev; |
| rdevs = 1; |
| } |
| } else if (s) { |
| if (vfs && vfs->dev) |
| dev = vfs->dev; |
| else |
| dev = DevDev; |
| devs = 1; |
| rdev = s->sn_vattr.va_rdev; |
| rdevs = 1; |
| if (!lkupdev(&dev, &rdev, 0, 0) && HaveCloneMaj) |
| rdev = makedev(CloneMaj, GET_MAJ_DEV(rdev)); |
| } else if (s5) { |
| dev = s5->i_dev; |
| devs = 1; |
| } else if (f) { |
| if (vfs && vfs->dev) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| } |
| /* |
| * Obtain the inode number. |
| */ |
| if (a) { |
| |
| #if ADVFSV>=500 |
| if (fscs) { |
| Lf->inode = (INODETYPE)fsc.st.num; |
| Lf->inp_ty = 1; |
| } |
| #else /* ADVFSV<500 */ |
| Lf->inode = (INODETYPE)a->a_number; |
| Lf->inp_ty = 1; |
| #endif /* ADVFSV>=500 */ |
| |
| |
| #if defined(HASTAGTOPATH) |
| /* |
| * Record the Digital UNIX 4.0 or greater, ADVFS 4.0 or greater |
| * ADVFS sequence number for later use with tag_to_path(). |
| */ |
| Lf->advfs_seq = a->a_seq; |
| Lf->advfs_seq_stat = 1; |
| #endif /* defined(HASTAGTOPATH) */ |
| |
| } else if (c) { |
| Lf->inode = (INODETYPE)c->cd_number; |
| Lf->inp_ty = 1; |
| } |
| |
| #if DUV>=50000 |
| else if (cn) { |
| if (cn->c_attr.va_mask & AT_NODEID) { |
| Lf->inode = (INODETYPE)cn->c_attr.va_fileid; |
| Lf->inp_ty = 1; |
| } |
| } |
| #endif /* DUV>=50000 */ |
| |
| else if (i) { |
| Lf->inode = (INODETYPE)i->i_number; |
| Lf->inp_ty = 1; |
| } else if (p) { |
| Lf->inode = (INODETYPE)((type == VDIR) ? PR_ROOTINO |
| : p->prc_pid + PR_INOBIAS); |
| Lf->inp_ty = 1; |
| } else if (r) { |
| Lf->inode = (INODETYPE)r->r_attr.va_fileid; |
| Lf->inp_ty = 1; |
| } else if (s5) { |
| Lf->inode = (INODETYPE)s5->i_number; |
| Lf->inp_ty = 1; |
| } |
| |
| #if DUV>=30000 |
| else if (f) { |
| Lf->inode = (INODETYPE)f->fn_fileid; |
| Lf->inp_ty = 1; |
| } |
| #endif /* DUV>=30000 */ |
| |
| /* |
| * Obtain the file size. |
| */ |
| if (Foffset) { |
| Lf->off_def = 1; |
| |
| #if DUV>=30000 |
| if (Ntype == N_FIFO && f) |
| Lf->off = (unsigned long) |
| (Lf->access == 'r') ? f->fn_rptr : f->fn_wptr; |
| #endif /* DUV>=30000 */ |
| |
| } else { |
| switch (Ntype) { |
| case N_FIFO: |
| |
| #if DUV>=30000 |
| if (f) { |
| Lf->sz = (SZOFFTYPE)f->fn_size; |
| Lf->sz_def = 1; |
| } else if (!Fsize) |
| Lf->off_def = 1; |
| #else /* DUV<30000 */ |
| if (!Fsize) |
| Lf->off_def = 1; |
| #endif /* DUV>=30000 */ |
| |
| break; |
| case N_NFS: |
| if (r) { |
| Lf->sz = (SZOFFTYPE)r->r_attr.va_qsize; |
| Lf->sz_def = 1; |
| } |
| break; |
| case N_REGLR: |
| if (type == VREG || type == VDIR) { |
| if (a) { |
| |
| #if ADVFSV>=500 |
| if (fscs) { |
| Lf->sz = (SZOFFTYPE)fsc.st.size; |
| Lf->sz_def = 1; |
| } |
| #else /* ADVFSV<500 */ |
| Lf->sz = (SZOFFTYPE)a->a_size; |
| Lf->sz_def = 1; |
| #endif /* ADVFSV>=500 */ |
| |
| } else if (c) { |
| Lf->sz = (SZOFFTYPE)c->cd_size; |
| Lf->sz_def = 1; |
| } |
| |
| #if DUV>=50000 |
| else if (cn) { |
| if (cn->c_attr.va_mask & AT_SIZE) { |
| Lf->sz = (SZOFFTYPE)cn->c_attr.va_qsize; |
| Lf->sz_def = 1; |
| } |
| } |
| #endif /* DUV>=50000 */ |
| |
| else if (i) { |
| Lf->sz = (SZOFFTYPE)i->i_din.di_qsize; |
| Lf->sz_def = 1; |
| } else if (m) { |
| Lf->sz = (SZOFFTYPE)m->mfs_size; |
| Lf->sz_def = 1; |
| } else if (p) { |
| if (type != VDIR) |
| get_proc_sz(p); |
| } else if (s5) { |
| Lf->sz = (SZOFFTYPE)s5->i_size; |
| Lf->sz_def = 1; |
| } |
| } else if ((type == VBLK) || (type == VCHR) && !Fsize) |
| Lf->off_def = 1; |
| } |
| } |
| if (Fnlink) { |
| switch(Ntype) { |
| case N_FIFO: /* no link count */ |
| break; |
| case N_NFS: |
| Lf->nlink = (long)r->r_attr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| case N_REGLR: |
| |
| # if ADVFSV>=400 |
| if (a) { |
| |
| #if ADVFSV>=500 |
| if (fscs) { |
| Lf->nlink = (long)fsc.st.nlink; |
| Lf->nlink_def = 1; |
| } |
| #else /* ADVFSV<500 */ |
| Lf->nlink = (long)a->a_nlink; |
| Lf->nlink_def = 1; |
| #endif /* ADVFSV>=500 */ |
| |
| break; |
| } |
| # endif /* ADVFSV>=400 */ |
| |
| if (c) { |
| Lf->nlink = (long)c->cd_nlink; |
| Lf->nlink_def = 1; |
| } |
| |
| #if DUV>=50000 |
| else if (cn) { |
| if (cn->c_attr.va_mask & AT_NLINK) { |
| Lf->nlink = (long)cn->c_attr.va_nlink; |
| Lf->nlink_def = 1; |
| } |
| } |
| #endif /* DUV>=50000 */ |
| |
| else if (i) { |
| Lf->nlink = (long)i->i_din.di_nlink; |
| Lf->nlink_def = 1; |
| } else if (s5) { |
| Lf->nlink = (long)s5->i_nlink; |
| Lf->nlink_def = 1; |
| } |
| } |
| if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) |
| Lf->sf |= SELNLINK; |
| } |
| /* |
| * Record an NFS file selection. |
| */ |
| if (Ntype == N_NFS && Fnfs) |
| Lf->sf |= SELNFS; |
| /* |
| * Save the device numbers and their states. |
| * |
| * Format the vnode type, and possibly the device name. |
| */ |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| switch (type) { |
| case VNON: |
| ty ="VNON"; |
| break; |
| case VREG: |
| case VDIR: |
| ty = (type == VREG) ? "VREG" : "VDIR"; |
| break; |
| case VBLK: |
| ty = "VBLK"; |
| Ntype = N_BLK; |
| break; |
| case VCHR: |
| ty = "VCHR"; |
| Ntype = N_CHR; |
| break; |
| case VLNK: |
| ty = "VLNK"; |
| break; |
| |
| #if defined(VSOCK) |
| case VSOCK: |
| ty = "SOCK"; |
| break; |
| #endif /* defined(VSOCK) */ |
| |
| case VBAD: |
| ty = "VBAD"; |
| break; |
| case VFIFO: |
| ty = "FIFO"; |
| |
| #if DUV>=30000 |
| if ((!devs || !dev) && f) { |
| vfs = (struct l_vfs *)NULL; |
| devs = Lf->dev_def = 0; |
| ul = (unsigned long)v->v_fifonode; |
| enter_dev_ch(print_kptr((KA_T)(ul&0xffffffff),(char *)NULL,0)); |
| } |
| #endif /* DUV>=30000 */ |
| |
| break; |
| default: |
| (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); |
| ty = (char *)NULL; |
| } |
| if (ty) |
| (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); |
| Lf->ntype = Ntype; |
| /* |
| * Save the file system names. |
| */ |
| if (vfs) { |
| if (vfs->dir && *vfs->dir) |
| Lf->fsdir = vfs->dir; |
| if (vfs->fsname && *vfs->fsname) |
| Lf->fsdev = vfs->fsname; |
| |
| #if defined(HASFSINO) |
| if (vfs->fs_ino) |
| Lf->fs_ino = vfs->fs_ino; |
| #endif /* defined(HASFSINO) */ |
| |
| } |
| /* |
| * Handle some special cases: |
| * |
| * ioctl(fd, TIOCNOTTY) files; |
| * FIFOs (Digital UNIX V3.0 and higher); |
| * memory node files; |
| * /proc files. |
| */ |
| |
| if (type == VBAD) |
| (void) snpf(Namech, Namechl, "(revoked)"); |
| if (m) { |
| devs = Lf->dev_def = Lf->rdev_def = rdevs = 0; |
| (void) snpf(Namech, Namechl, "%#x", m->mfs_baseoff); |
| (void) enter_dev_ch("memory"); |
| } else if (p) { |
| devs = Lf->dev_def = Lf->rdev_def = rdevs = 0; |
| if (type != VDIR) |
| (void) snpf(Namech, Namechl, "/proc/%d", p->prc_pid); |
| else |
| (void) snpf(Namech, Namechl, "/proc"); |
| } |
| |
| #if defined(HASBLKDEV) |
| /* |
| * If this is a VBLK file and it's missing an inode number, try to |
| * supply one. |
| */ |
| if ((Lf->inp_ty == 0) && (type == VBLK)) |
| find_bl_ino(); |
| #endif /* defined(HASBLKDEV) */ |
| |
| /* |
| * If this is a VCHR file and it's missing an inode number, try to |
| * supply one. |
| */ |
| if ((Lf->inp_ty == 0) && (type == VCHR)) |
| find_ch_ino(); |
| /* |
| * Test for specified file. |
| */ |
| if (p) { |
| if (Procsrch) { |
| Procfind = 1; |
| Lf->sf |= SELNM; |
| } else { |
| for (pfi = Procfsid; pfi; pfi = pfi->next) { |
| if ((pfi->pid && pfi->pid == p->prc_pid) |
| |
| #if defined(HASPINODEN) |
| || (Lf->inp_ty == 1 && pfi->inode == Lf->inode) |
| #endif /* defined(HASPINODEN) */ |
| |
| ) { |
| pfi->f = 1; |
| Lf->sf |= SELNM; |
| break; |
| } |
| } |
| } |
| } else { |
| if (Sfile && is_file_named((char *)NULL, (type == VCHR) ? 1 : 0)) |
| Lf->sf |= SELNM; |
| } |
| /* |
| * Enter name characters. |
| */ |
| if (Namech[0]) |
| enter_nm(Namech); |
| } |
| |
| |
| /* |
| * readvnode() - read vnode |
| */ |
| |
| static int |
| readvnode(va, v) |
| KA_T va; /* vnode kernel space address */ |
| struct vnode *v; /* vnode buffer pointer */ |
| { |
| |
| if (kread((KA_T)va, (char *)v, sizeof(struct vnode) - 1 + Vnmxp)) { |
| (void) snpf(Namech, Namechl, "can't read vnode at %s", |
| print_kptr(va, (char *)NULL, 0)); |
| return(1); |
| } |
| return(0); |
| } |