Pyramid version of ``find-fs''
Romain Kang
romain at pyrnj.uucp
Wed Feb 22 19:44:21 AEST 1989
This is a variation on the theme of /etc/fuser, even though only finds
open files on the same filesystem. However, it will work on NFS file
systems as well as local UNIX filesystems.
: shell archive -- use sh, not csh
: this archive contains:
: Makefile
: ffs.c
:
echo x - Makefile
cat > Makefile << '%-End-of-Makefile-%'
# uncomment these if you have snode.h
#INC = -I/usr/include -I/usr/src/osx
#SNODE = -DSNODE
# uncomment if you have OSx5.0
#OSX = -DOSx5_0
CC = ucb cc
CFLAGS = -OG $(INC) $(SNODE) $(OSX)
ffs: ffs.o
$(CC) -o ffs $?
ffs.o: Makefile
clean:
rm -f *.o core
clobber:
rm -f ffs *.o core
%-End-of-Makefile-%
echo x - ffs.c
cat > ffs.c << '%-End-of-ffs.c-%'
/*
* find-fs filesystem
*
* Finds processes accessing an nfs file system.
* Compile by cc -I/sys/h -o find-fs find-fs.c
*
* Copyright Richard Tobin, AIAI 1988 (R.Tobin at uk.ac.ed)
* May be freely redistributed if this notice remains intact.
*
* Modified by Valdis Kletnieks, Clarkson University
* to print out the inode-number as well. Run 'ncheck' to find
* what THAT points at.
*
* Pyramid version, Romain Kang (romain at pyrnj.UUCP)
* Added -q argument for quieter/quicker output.
* Support for remote NFS files (rnodes) and NFSSRC3.2 snodes.
* To get inode of device special files, you currently need kernel source.
* If you have snode.h, #define SNODE
*/
#define KERNEL 1 /* so we get the stuff we need */
/*#define SNODE /* if you have snode.h */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/vfs.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <ufs/inode.h> /* V. Kletnieks */
#include <rpc/rpc.h>
#include <nfs/nfs.h>
#include <nfs/rnode.h>
#include <stdio.h> /* must be after vfs - sigh */
#include <mntent.h>
#ifdef OSx5_0
# include <a.out.h>
# include <sys/immu.h>
# undef r_lock
# include <sys/region.h>
# define N_NAME n_un.n_name
#else
# include <nlist.h>
# include <sys/pte.h>
# include <sys/text.h>
# define N_NAME n_name
#endif
#ifdef SNODE
# include <specfs/snode.h>
#endif
#undef NOFILE
#define NOFILE (u->u_rlimit[RLIMIT_FDMAX].rlim_cur)
#undef KERNEL
struct user *get_user();
int check();
void name(), get_names(), kread(), error(), xperror();
fsid_t *fsid();
int kfd;
int qflag;
#ifndef OSx5_0
int mfd, sfd;
void mread();
#endif
#define Check(v,id,format,arg1,arg2) \
if (check(v,id,format,arg1,arg2)&&qflag) continue
main(argc, argv)
int argc;
char **argv;
{
int f;
int rc;
int k_proc, k_procNPROC;
struct proc *proc, *procNPROC, *paddr, p;
#undef u /* where is this??? */
struct user *u;
struct file file;
struct file **ofile;
#ifndef OSx5_0
struct text *p_text, text;
#else
reg_t *regp, region;
preg_t pregion;
#endif
fsid_t *id;
if (argc > 2 && strcmp(argv[1],"-q") == 0)
{
qflag++;
argv++;
argc--;
}
if (argc != 2)
error("usage: ffs filesystem");
id = fsid(argv[1]);
fprintf(stderr, "looking for id %x %x\n", id->val[0], id->val[1]);
kfd = open("/dev/kmem", O_RDONLY);
if(kfd < 0)
xperror("open: /dev/kmem");
#ifndef OSx5_0
mfd = open("/dev/mem", O_RDONLY);
if(mfd < 0)
xperror("open: /dev/mem");
sfd = open("/dev/drum", O_RDONLY);
if(sfd < 0)
xperror("open: /dev/drum");
#endif
name("_proc", &k_proc);
name("_procNPROC", &k_procNPROC);
get_names("/vmunix");
kread(k_proc, &proc, sizeof(proc));
kread(k_procNPROC, &procNPROC, sizeof(procNPROC));
for(paddr = proc; paddr < procNPROC; ++paddr)
{
kread(paddr, &p, sizeof(p));
if(p.p_pid <= 2) /* 1 and 2 cause problems */
continue;
#if OSx5_0
if (p.p_region)
{
kread(p.p_region, &pregion, sizeof(pregion));
if (regp = pregion.p_reg)
{
kread(regp, ®ion, sizeof(region));
Check(region.r_vptr, id, "process %d inode %d text\n", p.p_pid, 0);
}
}
#else
if (p.p_textp)
{
kread(p.p_textp, &text, sizeof(text));
Check(text.x_vptr, id, "process %d inode %d text\n", p.p_pid, 0);
}
#endif
if(p.p_stat == SZOMB) continue;
u = get_user(&p);
if(!u)
{
printf("warning: couldn't read u area for process %d\n", p.p_pid);
continue;
}
Check(u->u_cdir, id, "process %d inode %d current directory\n", p.p_pid, 0);
Check(u->u_rdir, id, "process %d inode %d root directory\n", p.p_pid, 0);
if (NOFILE > NFD_DEF)
{
int ofile_size = (NOFILE) * sizeof(struct file *);
printf("NOFILE = %d\n", NOFILE);
ofile = (struct file **)malloc(ofile_size);
kread(u->u_ofile, ofile, ofile_size);
}
else {
ofile = u->u_ofile_arr;
}
for (f = 0; f <= u->u_maxofile; f++)
{
if (ofile[f])
{
kread(ofile[f], &file, sizeof(file));
if (file.f_count > 0 && file.f_type == DTYPE_VNODE)
if (check(file.f_data, id, "process %d inode %d descriptor %d\n",
p.p_pid, f) && qflag)
break;
}
}
if (NOFILE > NFD_DEF)
free(ofile);
}
if (qflag>1)
putchar('\n');
exit(0);
}
check(v, id, format, arg1, arg2)
struct vnode *v;
fsid_t id[];
char *format;
int arg1, arg2;
{
struct vnode vnode;
struct inode inode;
struct rnode rnode;
struct vfs vfs;
if(!v)
return 0;
kread(v, &vnode, sizeof(vnode));
kread(vnode.v_vfsp, &vfs, sizeof(vfs));
if(bcmp(&vfs.vfs_fsid, id, sizeof(fsid_t)) == 0)
{
if (qflag)
{
printf((qflag>1) ? " %d" : "%d", arg1);
qflag++;
return 1;
}
#ifdef SNODE
/* Yes, the SNODE #ifdef is ugly... */
if (vnode.v_type == VCHR || vnode.v_type == VBLK)
{
struct snode snode;
kread(vnode.v_data, &snode, sizeof(snode));
kread(snode.s_realvp, &vnode, sizeof(vnode));
}
#else
if (vnode.v_type == VCHR || vnode.v_type == VBLK)
inode.i_number = -2;
else
#endif SNODE
if (vnode.v_flag&VREMOTE)
{
kread(vnode.v_data, &rnode, sizeof(rnode));
inode.i_number = rnode.r_nfsattr.na_nodeid;
}
else
kread(vnode.v_data, &inode, sizeof(inode));
printf(format, arg1, (int)inode.i_number, arg2);
return 1;
}
return 0;
}
#define MAXAD 50
struct nlist nl[MAXAD];
int *ad[MAXAD], nad=0;
void
name(nm, addr)
char *nm;
int *addr;
{
if(nad == MAXAD)
error("too many names");
nl[nad].N_NAME = nm;
ad[nad++] = addr;
}
void
get_names(file)
char *file;
{
char buf[100];
if(nlist(file, nl) < 0)
error("can't nlist /vmunix");
do
{
if(nl[--nad].n_type == N_UNDF)
{
sprintf(buf, "can't find symbol %s", nl[nad].N_NAME);
error(buf);
}
*ad[nad] = nl[nad].n_value;
}
while(nad > 0);
}
void
kread(address, buffer, size)
caddr_t address;
caddr_t buffer;
int size;
{
extern int errno;
if(lseek(kfd, (long)address, L_SET) == -1)
xperror("kmem seek");
errno = 0;
if(read(kfd, buffer, size) != size)
{
fprintf(stderr, "kaddr = 0x%x: ", address);
perror("kmem read");
abort();
}
}
#ifndef OSx5_0
void
mread(address, buffer, size)
int size;
char *address, *buffer;
{
extern int errno;
if(lseek(mfd, (long)address, L_SET) == -1)
xperror("mem seek");
errno = 0;
if(read(mfd, buffer, size) != size)
xperror("mem read");
}
#endif
void
error(message)
char *message;
{
fprintf(stderr, "%s\n", message);
exit(1);
}
void
xperror(message)
char *message;
{
perror(message);
exit(1);
}
struct user *
get_user(p)
struct proc *p;
{
static union {
struct user u;
char buf[UPAGES * PAGSIZ];
} ubuf;
struct user *u = &ubuf.u;
#ifdef OSx5_0
if (readublk(p->p_pid, u) == -1)
u = 0;
#else
struct pte ptes[UPAGES], *pte;
char *buf;
int bytes;
if(p->p_flag & SLOAD)
{
/* it's in memory */
kread(p->p_addr, ptes, sizeof(ptes));
for(bytes = sizeof(*u), pte = ptes, buf = (char *)u;
bytes > 0;
bytes -= NBPG, pte++, buf += NBPG)
mread(pte->pg_pfnum * NBPG, buf, bytes > NBPG ? NBPG : bytes);
}
else
{
/* read from swap */
if(lseek(sfd, (long)dtob(p->p_swaddr), L_SET) == -1)
xperror("swap seek");
if(read(sfd, u, sizeof(*u)) < sizeof(*u))
return (struct user *)0;
}
#endif
return u;
}
fsid_t *
fsid(name)
char *name;
{
static struct statfs fsbuf;
struct stat statbuf;
if(stat(name, &statbuf) < 0)
xperror("stat");
if(statbuf.st_dev < 0) /* seems to mean nfs */
{
if(statfs(name, &fsbuf) < 0)
xperror("statfs");
}
else
{
/* local UNIX file system */
fsbuf.f_fsid.val[0] = statbuf.st_dev;
fsbuf.f_fsid.val[1] = 0; /* MOUNT_UFS */
}
return &fsbuf.f_fsid;
}
%-End-of-ffs.c-%
More information about the Comp.sys.pyramid
mailing list