/* * dnode.c - AIX node reading 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.25 2008/10/21 16:14:18 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #if AIXV<5000 #define FL_NEXT next #else /* AIXV>=5000 */ #define FL_NEXT fl_next # if !defined(ISVDEV) #define ISVDEV(t) (((t)==VBLK)||((t)==VCHR)||((t)==VFIFO)||((t)==VMPC)) # endif /* !defined(ISVDEV) */ #endif /* AIXV<5000 */ # if defined(HAS_NFS) # if AIXV<4210 #include # else /* AIXV>=4210 */ # if AIXA<2 /* * Private rnode struct definitions for AIX 4.2.1 and above * * The rnode struct IBM ships in doesn't match the one * the kernel uses. The kernel's rnode struct definition comes from * , a header file IBM does not ship with AIX. * * The rnode64 struct is for AIX above 4.3.3 whose "width" is 64. * (See dnode.c for the method used to determine width.) */ struct rnode { caddr_t r_d1[11]; /* dummies; links? */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ caddr_t r_d2[29]; /* dummies; rnode elements? */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # if AIXV>4330 struct rnode64 { # if AIXV<5200 caddr_t r_d1[11]; /* dummies; links? */ # else /* AIXV>=5200 */ # if AIXV<5300 caddr_t r_d1[12]; /* dummies; links? */ # else /* AIXV>=5300 */ caddr_t r_d1[7]; /* dummies; links? */ # endif /* AIXV<5300 */ # endif /* AIXV<5200 */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ # if AIXV<5300 caddr_t r_d2[15]; /* dummies; rnode elements? */ # else /* AIXV>=5300 */ caddr_t r_d2[11]; /* dummies; rnode elements? */ # endif /* AIXV<5300 */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # endif /* AIXV>4330 */ # else /* AIXA>=2 */ struct rnode { KA_T d1[7]; /* dummies */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ KA_T d2[19]; /* dummies */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # endif /* AIXA<2 */ # endif /* AIXV<4210 */ # endif /* defined(HAS_NFS) */ /* * isglocked() - is a gnode locked */ char isglocked(ga) struct gnode *ga; /* local gnode address */ { struct filock *cfp, f, *ffp; int l; if (!(ffp = ga->gn_filocks)) return(' '); cfp = ffp; #if AIXV>=4140 do { #endif /* AIXV>=4140 */ if (kread((KA_T)cfp, (char *)&f, sizeof(f))) return(' '); #if AIXV>=4140 if (f.set.l_sysid || f.set.l_pid != (pid_t)Lp->pid) continue; #endif /* AIXV>=4140 */ if (f.set.l_whence == 0 && f.set.l_start == 0 #if AIXV>=4200 && f.set.l_end == 0x7fffffffffffffffLL #else /* AIXV<4200 */ && f.set.l_end == 0x7fffffff #endif /* AIXV>=4200 */ ) l = 1; else l = 0; switch (f.set.l_type & (F_RDLCK | F_WRLCK)) { case F_RDLCK: return((l) ? 'R' : 'r'); case F_WRLCK: return((l) ? 'W' : 'w'); case (F_RDLCK + F_WRLCK): return('u'); } return(' '); #if AIXV>=4140 } while ((cfp = f.FL_NEXT) && cfp != ffp); return(' '); #endif /* AIXV>=4140 */ } /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { struct cdrnode c; dev_t dev, rdev; int devs = 0; struct gnode g; struct l_ino i; int ic = 0; int ins = 0; struct vfs *la = NULL; int rdevs = 0; size_t sz; char tbuf[32], *ty; enum vtype type; struct l_vfs *vfs; static struct vnode *v = (struct vnode *)NULL; #if AIXV>=3200 struct devnode dn; struct gnode pg; struct specnode sn; struct fifonode f; #endif /* AIXV>=3200 */ #if defined(HAS_AFS) static int afs = 0; /* AFS test status: -1 = no AFS * 0 = not tested * 1 = AFS present */ struct afsnode an; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) struct vattr nfs_attr; int nfss = 0; static struct rnode r; static char *rp = (char *)&r; static int rsz = sizeof(r); # if AIXV>4330 && AIXA<2 static struct rnode64 r64; # endif /* AIXV>4330 && AIXA<2 */ # if AIXA<2 static int width = -1; # else /* AIXA>=2 */ static width = 64; # endif /* AIXA<2 */ #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) struct sanfs_node { /* DEBUG */ /* * This is a DEBUG version of the SANFS node structure. When IBM makes * the SANFS header files available in /usr/include, this definition * will be removed. */ u_long san_d1[20]; /* DEBUG */ struct gnode san_gnode; /* DEBUG */ u_long san_d2[128]; /* DEBUG */ } san; int sans = 0; #endif /* defined(HAS_SANFS) */ #if AIXV>=4140 struct clone *cl; KA_T ka; struct module_info mi; int ml, nx; char mn[32]; struct queue q; struct qinit qi; KA_T qp, xp; int ql; struct sth_s { /* stream head */ KA_T *dummy; /* dummy */ KA_T *sth_wq; /* write queue */ } sh; struct xticb { /* XTI control block */ int d1; long d2; int d3; struct socket *xti_so; /* socket pointer */ } xt; #endif /* AIXV>=4140 */ /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } if (!v) { /* * Allocate space for the vnode or AFS vcache structure. */ #if defined(HAS_AFS) v = alloc_vcache(); #else /* !defined(HAS_AFS) */ v = (struct vnode *)malloc((MALLOC_S)sizeof(struct vnode)); #endif /* defined(HAS_AFS) */ if (!v) { (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, #if defined(HAS_AFS) "vcache" #else /* !defined(HAS_AFS) */ "vnode" #endif /* defined(HAS_AFS) */ ); Exit(1); } } /* * Read the vnode. */ if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASFSTRUCT) Lf->fsv |= FSV_NI; Lf->fna = va; #endif /* defined(HASFSTRUCT) */ /* * Read the gnode. */ if (!v->v_gnode || readgnode((KA_T)v->v_gnode, &g)) { if (Selinet) { Lf->sf = SELEXCLF; return; } (void) snpf(Namech, Namechl, "vnode at %s has no gnode\n", print_kptr(va, (char *)NULL, 0)); enter_nm(Namech); return; } #if AIXV>=3200 /* * Under AIX 3.2 and above, if the vnode type is ISVDEV, then there is a * special node and a fifonode or devnode. Behind them are the "real" * gnode, inode and vnode. */ if (ISVDEV(g.gn_type)) { switch (g.gn_type) { case VBLK: Ntype = N_BLK; break; case VCHR: Ntype = N_CHR; break; case VFIFO: Ntype = N_FIFO; break; case VMPC: Ntype = N_MPC; break; default: (void) snpf(Namech, Namechl, "vnode at %s: unknown ISVDEV(%#x)", print_kptr(va, (char *)NULL, 0), g.gn_type); enter_nm(Namech); return; } /* * Read the special node. */ if (!g.gn_data || kread((KA_T)g.gn_data, (char *)&sn, sizeof(sn))) { if (Selinet) { Lf->sf = SELEXCLF; return; } (void) snpf(Namech, Namechl, "vnode at %s: can't read specnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read the PFS gnode and its inode and vnode. */ if (sn.sn_pfsgnode) { if (Selinet) { Lf->sf = SELEXCLF; return; } if (readgnode((KA_T)sn.sn_pfsgnode, &g)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read pfsgnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_pfsgnode, (char *)NULL, 0)); enter_nm(Namech); return; } if (!g.gn_data || readlino(&g, &i)) { (void) snpf(Namech, Namechl, "pfsgnode at %s: can't read inode (%s)", print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; if (!g.gn_vnode || readvnode((KA_T)g.gn_vnode, v)) { (void) snpf(Namech, Namechl, "pfsgnode at %s: can't read vnode (%s)", print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_vnode, (char *)NULL, 0)); enter_nm(Namech); return; } } else { (void) zeromem((char *)&i, sizeof(i)); #if AIXV>=4140 /* * See if this is a clone device, connected to a stream. * * the clone major device number must be known; * the specnode must have a devnode pointer; * and the devnode must have a stream head pointer. */ if (CloneMaj >= 0 && sn.sn_devnode && kread((KA_T)sn.sn_devnode, (char *)&dn, sizeof(dn)) == 0 && (ka = (KA_T)dn.dv_pdata)) { # if defined(HASDCACHE) process_clone_again: # endif /* defined(HASDCACHE) */ for (cl = Clone; cl; cl = cl->next) { if (GET_MAJ_DEV(g.gn_rdev) == GET_MIN_DEV(cl->cd.rdev)) { # if defined(HASDCACHE) if (DCunsafe && !cl->cd.v && !vfy_dev(&cl->cd)) goto process_clone_again; # endif /* defined(HASDCACHE) */ /* * Identify this file as a clone. Save the clone * device inode number as the file's inode number. */ ic = 1; Lf->inode = cl->cd.inode; Lf->inp_ty = 1; if (ClonePtc >= 0 && GET_MAJ_DEV(g.gn_rdev) == ClonePtc) { if (Selinet) { Lf->sf = SELEXCLF; return; } /* * If this is a /dev/ptc stream, enter the device * name and the channel. */ (void) snpf(Namech, Namechl, "%s/%d", cl->cd.name, (int)GET_MIN_DEV(g.gn_rdev)); break; } /* * If this isn't a /dev/ptc stream, collect the names * of the modules on the stream. Ignore the stream * head and look for an "xtiso" module. Limit the * module depth to 25. */ (void) snpf(Namech, Namechl, "STR:%s", cl->cd.name); nx = (int) strlen(Namech); if (!kread(ka, (char *)&sh, sizeof(sh))) qp = (KA_T)sh.sth_wq; else qp = (KA_T)NULL; for (mn[sizeof(mn) - 1] = '\0', ql = 0; qp && (ql < 25); ql++, qp = (KA_T)q.q_next) { /* * Read the queue structure. If it can't be read, * end module name collection. * * The queue structure should lead to a qinfo * structure, and the qinfo structure should lead * to a module_info structure, where the module * name should be found. If there's no queue * structure. * * If the qinfo or module_info structures can't be * read, skip to the next queue structure. */ if (kread(qp, (char *)&q, sizeof(q))) break; if (!(ka = (KA_T)q.q_qinfo) || kread(ka, (char *)&qi, sizeof(qi))) continue; if (!(ka = (KA_T)qi.qi_minfo) || kread(ka, (char *)&mi, sizeof(mi))) continue; if (!(ka = (KA_T)mi.mi_idname) || kread(ka, mn, sizeof(mn) - 1) || !(ml = (int) strlen(mn)) || !strcmp(mn, "sth")) continue; if (!strcmp(mn, "xtiso") && (xp = (KA_T)q.q_ptr) && !kread(xp, (char *)&xt, sizeof(xt)) && (ka = (KA_T)xt.xti_so)) { /* * The xtiso module's private queue pointer * leads to an xticb with a non-NULL socket * pointer. Process the stream as a socket. */ Namech[0] = '\0'; Lf->inp_ty = 0; (void) process_socket(ka); return; } /* * Save the module name in Mamech[] as a "->" * prefixed chain, beginning with "STR:". */ if ((nx + ml + 2) > (Namechl - 1)) continue; (void) snpf(&Namech[nx], Namechl, "->%s", mn); nx += (ml + 2); } break; } } } #endif /* AIXV>=4140 */ if (Selinet) { Lf->sf = SELEXCLF; return; } } /* * If it's a FIFO, read its fifonode. */ if (Ntype == N_FIFO) { if (!sn.sn_fifonode ||readfifonode((KA_T)sn.sn_fifonode, &f)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read fifonode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_fifonode, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Otherwise, read the devnode and its gnode. */ } else { if (!sn.sn_devnode || kread((KA_T)sn.sn_devnode,(char *)&dn,sizeof(dn))) { (void) snpf(Namech, Namechl, "vnode at %s: can't read devnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_devnode, (char *)NULL, 0)); enter_nm(Namech); return; } g = dn.dv_gnode; } } #endif /* AIXV>=3200 */ /* * Read the AIX virtual file system structure. */ if (Ntype != N_AFS && g.gn_rdev == NODEVICE) { vfs = (struct l_vfs *)NULL; enter_dev_ch(print_kptr(va, (char *)NULL, 0)); } else { if (!(vfs = readvfs(v))) { (void) snpf(Namech, Namechl, "can't read vfs for %s at %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0)); enter_nm(Namech); return; } } /* * Set special node types: NFS, PROC or SANFS. */ #if defined(MNT_REMOTE) if (vfs && vfs->vmt_flags & MNT_REMOTE) { switch(vfs->vmt_gfstype) { # if defined(HAS_NFS) case MNT_NFS: # if defined(MNT_NFS3) case MNT_NFS3: # endif /* defined(MNT_NFS3) */ # if defined(MNT_NFS4) case MNT_NFS4: # endif /* defined(MNT_NFS4) */ # if defined(HAS_AFS) if (!AFSVfsp || (KA_T)v->v_vfsp != AFSVfsp) # endif /* defined(HAS_AFS) && defined(HAS_NFS) */ Ntype = N_NFS; # endif /* defined(HAS_NFS) */ break; # if defined(HAS_SANFS) && defined(MNT_SANFS) case MNT_SANFS: Ntype = N_SANFS; break; # endif /* defined(HAS_SANFS) && defined(MNT_SANFS) */ } } #endif /* defined(MNT_REMOTE) */ #if defined(HASPROCFS) if (vfs && (vfs->vmt_gfstype == MNT_PROCFS)) Ntype = N_PROC; #endif /* defined(HASPROCFS) */ /* * Get the lock status. */ Lf->lock = isglocked(&g); switch (Ntype) { #if defined(HAS_NFS) /* * Read an NFS rnode. */ case N_NFS: # if AIXA<2 if (width == -1) { /* * Establish the architecture's bit width and set NFS rnode * access parameters accordingly. */ # if AIXV<=4330 width = 32; # else /* AIXV>4330 */ if (__KERNEL_64()) { width = 64; rp = (char *)&r64; rsz = sizeof(r64); } else if (__KERNEL_32()) { width = 32; } else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: unknown kernel bit size\n", Pn); width = -2; } # endif /* AIXV<-4330 */ } # endif /* AIXA<2 */ if (width > 0) { if (!g.gn_data || kread((KA_T)g.gn_data, rp, rsz)) { (void) snpf(Namech, Namechl, "remote gnode at %s has no rnode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } # if AIXV<=4330 || AIXA>=2 nfs_attr = r.r_attr; nfss = 1; # else /* AIXV>4330 && AIXA<2 */ switch (width) { case 32: nfs_attr = r.r_attr; nfss = 1; break; case 64: nfs_attr = r64.r_attr; nfss = 1; break; } # endif /* AIXV<=4330 || AIXA>=2 */ } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) /* * Read SANFS node and associated structures. */ case N_SANFS: if (!g.gn_data || kread((KA_T)g.gn_data, &san, sizeof(san)) ) { (void) snpf(Namech, Namechl, "gnode at %s has no SANFS node", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } /* * DEBUG: this code is insufficient. It can't be completed until IBM * makes the SANFS header files available in /usr/include. There are * apparently two node structures following the SANFS node and file * attributes (size, etc.) are in the second structure. */ sans = 1; break; #endif /* defined(HAS_SANFS) */ /* * Read N_REGLR nodes. */ case N_REGLR: if (vfs && vfs->vmt_gfstype == MNT_CDROM) { /* * Read a CD-ROM cdrnode. */ if (!g.gn_data || readcdrnode((KA_T)g.gn_data, &c)) { (void) snpf(Namech, Namechl, "gnode at %s has no cdrnode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } (void) zeromem((char *)&i, sizeof(i)); i.number = (INODETYPE)c.cn_inumber; i.size = (off_t)c.cn_size; i.number_def = i.size_def = 1; /* * Otherwise, read the inode. */ } else if (g.gn_data) { if (readlino(&g, &i)) { (void) snpf(Namech, Namechl, "gnode at %s can't read inode: %s", print_kptr((KA_T)v->v_gnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; } #if defined(HAS_AFS) else { /* * See if this is an AFS node. */ if (AFSVfsp && (KA_T)v->v_vfsp == AFSVfsp) Ntype = N_AFS; else if (v->v_vfsp) { switch (afs) { case -1: break; case 0: if (!hasAFS(v)) { afs = 1; break; } afs = 1; Ntype = N_AFS; break; case 1: if ((KA_T)v->v_vfsp == AFSVfsp) Ntype = N_AFS; } } /* * If this is an AFS node, read the afsnode. */ if (Ntype == N_AFS) { if (readafsnode(va, v, &an)) return; } else { (void) snpf(Namech, Namechl, "gnode at %s has no inode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } } #else /* !defined(HAS_AFS) */ else { (void) snpf(Namech, Namechl, "gnode at %s has no inode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* defined(HAS_AFS) */ } /* * Get device and type for printing. */ #if defined(HAS_NFS) if (Ntype == N_NFS) { if (vfs) { dev = vfs->dev; devs = 1; } } else #endif /* defined(HAS_NFS) */ #if defined(HAS_AFS) if (Ntype == N_AFS) { dev = an.dev; devs = 1; } else #endif /* defined(HAS_AFS) */ #if defined(HASPROCFS) if (Ntype == N_PROC) { /* WARNING!!! WARNING!!! The following hack should be removed ASAP!!! */ dev = vfs ? (vfs->dev & 0x7fffffffffffffff) : 0; /* WARNING!!! WARNING!!! The above hack should be removed ASAP!!! */ devs = 1; } else #endif /* defined(HASPROCFS) */ #if defined(HAS_SANFS) if ((Ntype == N_SANFS) && vfs) { dev = vfs->dev; devs = 1; } else #endif /* defined(HAS_SANFS) */ { if (vfs) { dev = vfs->dev; devs = 1; } rdev = g.gn_rdev; rdevs = 1; } #if AIXV>=3200 if (Ntype == N_MPC) type = VMPC; else #endif /* AIXV>=3200 */ type = g.gn_type; /* * Obtain the inode number. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: if (an.ino_st) { Lf->inode = (INODETYPE)an.inode; Lf->inp_ty = 1; } break; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->inode = (INODETYPE)nfs_attr.va_serialno; Lf->inp_ty = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed until * IBM makes the SANFS header files available in /usr/include. */ /* Lf->inode = ??? DEBUG */ Lf->inp_ty = 1; } break; #endif /* defined(HAS_SANFS) */ # if AIXV>=3200 case N_BLK: case N_CHR: case N_FIFO: case N_MPC: # endif /* AIXV>=3200 */ case N_REGLR: if (ins) { Lf->inode = (INODETYPE)i.number; Lf->inp_ty = i.number_def; } } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->sz = (SZOFFTYPE)an.size; Lf->sz_def = 1; break; #endif /* defined(HAS_AFS) */ #if AIXV>=3200 case N_FIFO: Lf->sz = (SZOFFTYPE)f.ff_size; Lf->sz_def = 1; break; #endif /* AIXV>=3200 */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->sz = (SZOFFTYPE)nfs_attr.va_size; Lf->sz_def = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed * until IBM makes the SANFS header files available in * /usr/include. */ /* Lf->sz = (SZOFFTYPE)??? DEBUG */ Lf->sz_def = 1; } break; #endif /* defined(HAS_SANFS) */ #if AIXV>=3200 case N_BLK: if (!Fsize) Lf->off_def = 1; break; case N_CHR: case N_MPC: if (!Fsize) Lf->off_def = 1; break; #endif /* AIXV>=3200 */ case N_REGLR: if (type == VREG || type == VDIR) { if (ins) { Lf->sz = (SZOFFTYPE)i.size; Lf->sz_def = i.size_def; } } else if (((type == VBLK) || (type == VCHR) || (type == VMPC)) && !Fsize) Lf->off_def = 1; break; } } /* * Record link count. */ if (Fnlink) { switch(Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->nlink = an.nlink; Lf->nlink_def = an.nlink_st; break; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->nlink = (long)nfs_attr.va_nlink; Lf->nlink_def = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed * until IBM makes the SANFS header files available in * /usr/include. */ /* Lf->nlink = (long)??? DEBUG */ Lf->nlink_def = 1; } break; #endif /* defined(HAS_SANFS) */ #if AIXV>=3200 case N_BLK: case N_CHR: case N_FIFO: case N_MPC: #endif /* AIXV>=3200 */ case N_REGLR: if (ins) { Lf->nlink = (long)i.nlink; Lf->nlink_def = i.nlink_def; } break; } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } #if defined(HAS_NFS) /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; #endif /* defined(HAS_NFS) */ /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; } /* * Save the device numbers and their states. * * Format the vnode type. */ switch (type) { case VNON: ty ="VNON"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VBLK: ty = "VBLK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #endif case VBAD: ty = "VBAD"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VFIFO: if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') { Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; } ty = "FIFO"; break; case VMPC: Lf->rdev = g.gn_rdev; Lf->rdev_def = 1; if (vfs) { Lf->dev = vfs->dev; Lf->dev_def = 1; } Lf->ch = g.gn_chan; #if AIXV<3200 Lf->inp_ty = 0; #endif /* AIXV<3200 */ Ntype = N_CHR; ty = "VMPC"; break; default: Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; (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; #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 (Sfile && is_file_named(NULL, type, g.gn_chan, ic)) Lf->sf |= SELNM; /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #if defined(HASPRIVFILETYPE) /* * process_shmt() -- process shared memory transport file */ void process_shmt(sa) KA_T sa; /* shared memory transport node struct * address ??? */ { struct shmtnode { /* shared memory transport node * struct ??? */ struct shmtnode *peer; /* peer shmtnode struct */ caddr_t d1[2]; /* dummy to fill space */ int sz; /* buffer size */ caddr_t d2[3]; /* dyummy to fill space */ int free; /* free bytes in buffer */ caddr_t d3[17]; /* dummy to fill space */ pid_t pid; /* process ID */ } mn, pn; /* * Ignore this file if only Internet files are selected. */ if (Selinet) { Lf->sf |= SELEXCLF; return; } /* * Set type to " SMT" and put shmtnode structure address in device column. */ (void) snpf(Lf->type, sizeof(Lf->type), " SMT"); if (!sa || kread((KA_T)sa, (char *)&mn, sizeof(mn))) { (void) snpf(Namech, Namechl, "can't read shmtnode: %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); /* * If offset display has been requested or if buffer size less free bytes is * negative, enable offset display. Otherwise set the file size as buffer * size less free bytes. */ if (Foffset || mn.free > mn.sz) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)(mn.sz - mn.free); Lf->sz_def = 1; } /* * If there is a peer, read its shmtnode structure. */ if (!mn.peer) (void) snpf(Namech, Namechl, "->(unknown)"); else { if (kread((KA_T)mn.peer, (char *)&pn, sizeof(pn))) (void) snpf(Namech, Namechl, "can't read peer shmtnode: %s", print_kptr((KA_T)mn.peer, (char *)NULL, 0)); else { if (pn.pid) (void) snpf(Namech, Namechl, "->%s (PID %d)", print_kptr((KA_T)mn.peer, (char *)NULL, 0), pn.pid); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)mn.peer, (char *)NULL, 0)); } } enter_nm(Namech); } #endif /* AIXV>=4200 */ /* * readlino() -- read local inode */ int readlino(ga, li) struct gnode *ga; /* gnode address */ struct l_ino *li; /* local inode receiver */ { struct inode i; /* "regular" inode */ #if defined(HAS_JFS2) static struct vnodeops *j2va = (struct vnodeops *)NULL; /* j2_vnops address */ static int j2vas = 0; /* j2nl[] status */ #endif /* defined(HAS_JFS2) */ zeromem((char *)li, sizeof(struct l_ino)); if (!ga || !ga->gn_data) return(0); #if defined(HAS_JFS2) if (!j2vas) { /* * Get the j2_vnops address once. */ struct nlist j2nl[] = { { "j2_vnops" }, { (char *)NULL } }; if (nlist(N_UNIX, j2nl) == 0) j2va = (struct vnodeops *)j2nl[0].n_value; if (!j2va && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't identify jfs2 files\n", Pn); } j2vas = 1; } /* * If this system has jfs2, see if this gnode's operation structure pointer * references j2_vnops. */ if (ga->gn_ops && j2va && (ga->gn_ops == j2va)) return(readj2lino(ga, li)); #endif /* defined(HAS_JFS2) */ /* * Read a "standard" inode. */ if (readinode((KA_T)ga->gn_data, &i)) return(1); li->dev = i.i_dev; li->nlink = i.i_nlink; li->number = (INODETYPE)i.i_number; li->size = i.i_size; li->dev_def = li->nlink_def = li->number_def = li->size_def = 1; return(0); }