/* * dnode1.h - NEXTSTEP and OPENSTEP AFS support */ /* * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.7 2005/08/08 19:54:03 abe Exp $"; #endif #if defined(HAS_AFS) #include "lsof.h" #include #define __XDR_INCLUDE__ #include #include #include #include /* * This is an emulation of the afs_rwlock_t definition that appears in * the AFS sources in afs/lock.h. */ struct afs_lock { # if HAS_AFS<304 unsigned char d1[4]; # else /* HAS_AFS>=304 */ unsigned char d1[6]; # endif /* HAS_AFS<304 */ }; typedef struct afs_lock afs_lock_t; typedef struct afs_lock afs_rwlock_t; /* * This is an emulation of the afs_bozoLock_t definition that appears in * the AFS sources in afs/lock.h. */ struct afs_bozoLock { short d1; char d2[2]; char *d3; }; typedef struct afs_bozoLock afs_bozoLock_t; #define KERNEL #include #undef KERNEL /* * Local function prototypes */ _PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols)); _PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid)); /* * alloc_vcache() - allocate space for vcache structure */ struct vnode * alloc_vcache() { return((struct vnode *)malloc(sizeof(struct vcache))); } /* * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file */ void ckAFSsym(nl) struct nlist *nl; /* copy of Nl[] when empty */ { char *path = AFSAPATHDEF; int i; # if defined(HASAOPT) if (AFSApath) path = AFSApath; # endif /* defined(HASAOPT) */ /* * See if the alternate AFS name list file can be read. */ if (!is_readable(path, 0)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't access AFS name list file: %s\n", Pn, path); return; } /* * Read the AFS modload symbols and compare its non-zero values with * the non-zero values in Nl[]. Quit if there is any mis-match. */ if (nlist(path, nl) < 0) return; for (i = 0; Nl[i].n_un.n_name && Nl[i].n_un.n_name[0]; i++) { if (!nl[i].n_value || !Nl[i].n_value) continue; if (nl[i].n_value != Nl[i].n_value) return; } /* * If any AFS kernel name list symbol that doesn't have a value in Nl[] has * one from the AFS modload file, copy its modload value to Nl[]. */ if ((i = get_Nl_value("arFid", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avops", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avol", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; } /* * getvolume() - get volume structure */ static struct volume * getvolume(f, vols) struct VenusFid *f; /* file ID pointer */ int *vols; /* afs_volumes status return */ { int i; static KA_T ka = 0; KA_T kh; static struct volume v; struct volume *vp; static int w = 0; if (!ka) { if (get_Nl_value("avol", Drive_Nl, (unsigned long *)&ka) < 0 || !ka) { if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: no kernel address for afs_volumes\n", Pn); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } *vols = 0; return((struct volume *)NULL); } } *vols = 1; i = (NVOLS - 1) & f->Fid.Volume; kh = (KA_T)((char *)ka + (i * sizeof(struct volume *))); if (kread(kh, (char *)&vp, sizeof(vp))) return((struct volume *)NULL); while (vp) { if (kread((KA_T)vp, (char *)&v, sizeof(v))) return((struct volume *)NULL); if (v.volume == f->Fid.Volume && v.cell == f->Cell) return(&v); vp = v.next; } return((struct volume *)NULL); } /* * hasAFS() - test for AFS presence via vfs structure */ int hasAFS(vp) struct vnode *vp; /* vnode pointer */ { struct mounts *mp; int n; struct vfs v; /* * If this vnode has a v_data pointer, then it probably isn't an AFS vnode; * return FALSE. * * If the vfs struct address of /afs is known and this vnode's v_vfsp matches * it, return TRUE. * * Read this vnode's vfs structure and see if it's device (fsid.val[0]) is * AFSDEV. If it is, record the AFS vfs struct address and return TRUE. */ if (AFSVfsp && !vp->v_data && vp->v_vfsp == AFSVfsp) return(1); if (vp->v_data || !vp->v_vfsp || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v)) || v.vfs_data) return(0); if (v.vfs_fsid.val[0] == AFSDEV) { AFSVfsp = vp->v_vfsp; return(1); } /* * Search the local mount table for /afs devices or a match on device number. * Count /afs devices and skip a device number test for them. A match on * device number for non-AFS devices produces a FALSE return. */ for (mp = readmnt(), n = 0; mp; mp = mp->next) { if (mp->dev == AFSDEV && mp->dir && strcmp(mp->dir, "/afs") == 0 && mp->fsname && strcmp(mp->fsname, "AFS") == 0) n++; else if (mp->dev == (dev_t)v.vfs_fsid.val[0]) return(0); } /* * If there is exactly one /afs device, assume its vfs struct address is * the one for this vnode, record it, and return TRUE. */ if (n == 1) { AFSVfsp = vp->v_vfsp; return(1); } return(0); } /* * is_rootFid() - is the file ID the root file ID * * return: 0 = is not root file ID * 1 = is root file ID * rfid = 0 if root file ID structure address not available * 1 if root file ID structure address available */ static int is_rootFid(vc, rfid) struct vcache *vc; /* vcache structure */ int *rfid; /* root file ID pointer status return */ { unsigned long arFid; char *err; static int f = 0; /* rootFid structure status: * -1 = unavailable * 0 = not yet accessed * 1 = available */ static struct VenusFid r; static int w = 0; switch (f) { case -1: if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); case 0: if (get_Nl_value("arFid", Drive_Nl, &arFid) < 0 || !arFid) { err = "no _afs_rootFid kernel address"; rfid_unavailable: if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: AFS root Fid error: %s\n", Pn, err); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } f = -1; if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); } if (kread((KA_T)arFid, (char *)&r, sizeof(r))) { err = "can't read _afs_rootFid from kernel"; goto rfid_unavailable; } f = 1; /* fall through */ case 1: *rfid = 1; if (vc->fid.Fid.Unique == r.Fid.Unique && vc->fid.Fid.Vnode == r.Fid.Vnode && vc->fid.Fid.Volume == r.Fid.Volume && vc->fid.Cell == r.Cell) return(1); } *rfid = 0; return(0); } /* * readafsnode() - read AFS node */ int readafsnode(va, v, an) caddr_t va; /* kernel vnode address */ struct vnode *v; /* vnode buffer pointer */ struct afsnode *an; /* afsnode recipient */ { char *cp; KA_T ka; int len, rfid, vols; struct vcache *vc; struct volume *vp; cp = ((char *)v + sizeof(struct vnode)); ka = (KA_T)((char *)va + sizeof(struct vnode)); len = sizeof(struct vcache) - sizeof(struct vnode); if (kread(ka, cp, len)) { (void) snpf(Namech, Namechl, "vnode at %#x: can't read vcache remainder from %#x", va, ka); enter_nm(Namech); return(1); } vc = (struct vcache *)v; an->dev = AFSDEV; an->size = (unsigned long)vc->m.Length; an->nlink = (long)vc->m.LinkCount; an->nlink_st = 1; /* * Manufacture the "inode" number. */ if (vc->mvstat == 2) { if ((vp = getvolume(&vc->fid, &vols))) { an->inode = (INODETYPE)(vp->mtpoint.Fid.Vnode + (vp->mtpoint.Fid.Volume << 16)); if (an->inode == (INODETYPE)0) { if (is_rootFid(vc, &rfid)) an->ino_st = 1; else if (rfid) { an->inode = (INODETYPE)2; an->ino_st = 1; } else an->ino_st = 0; } else an->ino_st = 1; } else { if (vols) { an->inode = (INODETYPE)2; an->ino_st = 1; } else { if (v->v_flag & VROOT) { an->inode = (INODETYPE)0; an->ino_st = 1; } else an->ino_st = 0; } } } else { an->inode = (INODETYPE)((vc->fid.Fid.Vnode + (vc->fid.Fid.Volume << 16)) & 0x7fffffff); an->ino_st = 1; } return(0); } #endif /* defined(HAS_AFS) */