Thread View: comp.sys.sequent
1 messages
1 total messages
Started by rsk
Thu, 14 May 1987 02:17
new ofiles for vnode file systems: 4.3/nfs, sun, sequent (Msg. 2.4)
Author: rsk
Date: Thu, 14 May 1987 02:17
Date: Thu, 14 May 1987 02:17
748 lines
18247 bytes
18247 bytes
I have taken ofiles and rewritten it to work correctly for remote filesystems,
character special devices, and block special devices (as devices). I have
tested it on Sun 3.2 and 4.3+NFS (Wisconsin), but I'm sure I haven't got it
quite right for the sequent (we don't have one). I certainly don't have the
#includes right. Perhaps someone with access to a sequent could get it working
and mail me their working copy, so I can include it in the further enhancements
I am making. I used getopt() - if you don't have a copy you can get it from
any mod.sources archive or send me mail and I'll send you a copy.
This posting doesn't include a man page - the only added flag is "-f" which
prevents looking up arguments in /etc/mtab - useful if you want to see if
anyone has your filesystems' block special devices open as devices.
Because of the the way /dev/tty is implemented, you can't say "ofiles /dev/tty"
to find processes with their controlling tty open. But "ofiles /dev/ttya" or
"ofiles /dev/null" works fine.
@alex
---
arpanet: dupuy@columbia.edu
uucp: ...!seismo!columbia!dupuy
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
:
: ofiles.c
:
echo x - ofiles.c
sed 's/^X//' > ofiles.c << '//go.sysin dd *'
X#include <sys/param.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#ifdef sequent
X# define KERNEL
X# include <sys/file.h>
X# include <sys/vnode.h>
X# include <sys/vfs.h>
X# include <sys/inode.h>
X# include <rpc/types.h>
X# include <nfs/nfs.h>
X# include <netinet/in.h>
X# include <nfs/nfs_clnt.h>
X# include <nfs/rnode.h>
X# undef KERNEL
X#else
X# define KERNEL
X# include <sys/file.h>
X# undef KERNEL
X# include <sys/vnode.h>
X# include <sys/vfs.h>
X# include <ufs/inode.h>
X# include <rpc/types.h>
X# include <nfs/nfs.h>
X# include <netinet/in.h>
X# include <nfs/nfs_clnt.h>
X# include <nfs/rnode.h>
X#endif
X#include <machine/pte.h>
X#include <sys/vmmac.h>
X#include <sys/proc.h>
X#include <nlist.h>
X#include <sys/stat.h>
X#include <strings.h>
X#include <stdio.h>
X#include <mntent.h>
X#include <pwd.h>
X
Xunion fileid
X{
X struct
X {
X long fsid;
X long nodeid;
X } file;
X struct
X {
X dev_t dev;
X enum vtype type;
X } special;
X};
X
X#define CDIR 01
X#define OFILE 02
X#define RDIR 04
X
Xlong eseek ();
Xint eread ();
Xchar *vtype ();
Xchar *itype ();
Xchar *rtype ();
Xstruct mntent *getmntname ();
Xstruct mntent *getmntfile ();
Xunion fileid *getfileid ();
Xstruct user *getuser ();
X
X#define error(s) (perror ((s) ? (s) : ""), exit (1))
X
X#define istype(mode,type) (((mode) & S_IFMT) == (type))
X#define ispecial(mode) (istype ((mode), S_IFBLK) || istype ((mode), S_IFCHR))
X
X#define vspecial(vtype) ((vtype) == VCHR || (vtype) == VBLK)
X
X#define nfsdev(rdev) (major (rdev) == 0xff)
X
X/*
X * File descriptors.
X */
X
Xint mem; /* fd for /dev/mem */
Xint kmem; /* fd for /dev/kmem */
Xint swap; /* fd for /dev/drum */
X
XFILE *mtab; /* stdio file for /etc/mtab */
X
X/*
X * Kernel tables.
X */
X
X#ifdef sequent
X# define UNIX "/dynix"
X#else
X# define UNIX "/vmunix"
X#endif
Xstruct nlist nl[] =
X{
X#define X_PROC 0
X {"_proc"},
X#define X_NPROC 1
X {"_nproc"},
X#define X_USRPTMA 2
X {"_Usrptmap"},
X#define X_USRPT 3
X {"_usrpt"},
X {0}
X};
Xlong procbase; /* address of process table */
Xint nproc; /* number of entries in proc table */
Xstruct pte *Usrptma, /* user page table map */
X *usrpt; /* user page table */
X
Xint inodes[NOFILE]; /* inodes of open files */
X
X/*
X * Program options.
X */
X
Xchar *progname;
Xint terse = 0; /* if non-zero, only output pids */
Xint debug = 10; /* turn on debugging output */
Xint filesonly = 0; /* match args as files, not mntents */
Xint inode = 0; /* if non-zero, inode to match */
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X char filename[MNTMAXSTR],
X fsname[MNTMAXSTR];
X struct stat stats;
X struct mntent *mnt;
X
X extern char *optarg;
X extern int optind;
X int option;
X int usage = 0;
X
X progname = argv[0];
X
X while ((option = getopt (argc, argv, "pfd:")) != EOF)
X {
X switch (option)
X {
X case 'p':
X terse = 1;
X break;
X
X case 'f':
X filesonly = 1;
X break;
X
X case 'd':
X debug = atoi (optarg);
X break;
X
X case '?':
X usage = 1;
X }
X }
X if (!(argc -= optind) || usage)
X {
X fprintf (stderr, "usage: %s [-p] files\n", progname);
X exit (1);
X }
X
X if ((mem = open ("/dev/mem", 0)) < 0)
X error ("can't open /dev/mem. ");
X if ((kmem = open ("/dev/kmem", 0)) < 0)
X error ("can't open /dev/kmem. ");
X if ((swap = open ("/dev/drum", 0)) < 0)
X error ("can't open /dev/drum. ");
X
X if ((mtab = setmntent (MOUNTED, "r")) == 0)
X error ("can't open /etc/mtab. ");
X
X getsyms ();
X
X for (argv += optind; argc--; argv++)
X {
X /*
X * Check for filesystem/mountpoint vs. file.
X */
X
X if (!filesonly && (mnt = getmntname (*argv)) != NULL)
X {
X inode = 0; /* match any inode on this fs */
X strcpy (filename, mnt->mnt_dir);
X strcpy (fsname, mnt->mnt_fsname);
X }
X else
X {
X inode = 1; /* match only one inode */
X strcpy (filename, *argv);
X }
X
X if (stat (filename, &stats)) /* find out what it is we want */
X {
X perror (filename);
X continue;
X }
X
X if (inode) /* looking for file */
X {
X inode = stats.st_ino;
X if ((mnt = getmntfile (&stats)) != NULL)
X strcpy (fsname, mnt->mnt_fsname);
X else
X strcpy (fsname, "unknown");
X }
X
X if (!terse)
X {
X printf ("%s:\t%s\n", fsname, filename);
X
X if (debug > 5)
X if (ispecial (stats.st_mode))
X printf (" %s device %d/%d\n", itype (stats.st_mode),
X major (stats.st_rdev), minor (stats.st_rdev));
X else if (nfsdev (stats.st_dev))
X printf (" inode %d on remote fs %d (%s)\n",
X stats.st_ino, minor (stats.st_dev),
X itype (stats.st_mode));
X else
X printf (" inode %d on block device %x (%s)\n",
X stats.st_ino, stats.st_dev, itype (stats.st_mode));
X
X printf ("user\t process command\ttype\tinode(s)\n");
X }
X
X lookfor (&stats);
X }
X}
X
Xstruct mntent *
Xgetmntname (name)
Xchar *name;
X{
X register struct mntent *mnt;
X
X rewind (mtab);
X while ((mnt = getmntent (mtab)) != 0)
X {
X if (strcmp (name, mnt->mnt_fsname) == 0)
X return (mnt);
X if (strcmp (name, mnt->mnt_dir) == 0)
X return (mnt);
X }
X return (NULL);
X}
X
Xstruct mntent *
Xgetmntfile (filestats)
Xstruct stat *filestats;
X{
X register struct mntent *mnt;
X struct stat dirstats;
X
X rewind (mtab);
X while ((mnt = getmntent (mtab)) != 0)
X if ((stat (mnt->mnt_dir, &dirstats) >= 0) &&
X (filestats->st_dev == dirstats.st_dev))
X return (mnt);
X
X return (NULL);
X}
X
Xlookfor (filestats)
Xstruct stat *filestats;
X{
X struct proc p;
X struct user *u;
X register int procn,
X flags,
X filen;
X
X for (procn = 0; procn < nproc; procn++)
X {
X procslot (procn, &p);
X flags = 0;
X if (p.p_stat == 0 || p.p_stat == SZOMB)
X continue;
X u = getuser (&p);
X if (u == (struct user *) NULL)
X continue;
X
X if (debug > 10)
X printf ("uid %d pid %d command %s\n", p.p_uid, p.p_pid, u->u_comm);
X
X if (u->u_rdir != NULL)
X if (check (filestats, getfileid (u->u_rdir, "rdir")))
X flags |= RDIR;
X
X if (u->u_cdir != NULL)
X if (check (filestats, getfileid (u->u_cdir, "cdir")))
X flags |= CDIR;
X
X for (filen = 0; filen < NOFILE; filen++)
X {
X struct file f;
X union fileid *fid;
X
X inodes[filen] = 0;
X
X if (u->u_ofile[filen] == NULL)
X continue;
X
X eseek (kmem, (long) u->u_ofile[filen], 0, "file");
X eread (kmem, (char *) &f, sizeof (f), "file");
X
X if (f.f_count > 0)
X {
X if (f.f_type != DTYPE_VNODE)
X continue;
X
X fid = getfileid ((struct vnode *) f.f_data, "ofile");
X if (check (filestats, fid))
X {
X flags |= OFILE;
X if (!ispecial (filestats->st_mode))
X inodes[filen] = fid->file.nodeid;
X }
X }
X }
X if (flags)
X gotone (u, &p, flags);
X }
X}
X
X/*
X * Print the name of the user owning process "p" and the pid of that process
X */
X
Xgotone (u, p, f)
Xstruct user *u;
Xstruct proc *p;
Xint f;
X{
X struct passwd *getpwuid ();
X register struct passwd *pw;
X register int filen;
X
X if (terse) /* only print pids and return */
X {
X printf ("%d ", p->p_pid);
X fflush (stdout);
X return;
X }
X
X pw = getpwuid (p->p_uid);
X if (pw)
X printf ("%-8.8s", pw->pw_name);
X else
X printf ("(%d)\t", p->p_uid);
X
X printf (" %d\t", p->p_pid);
X
X printf (" %-14.14s\t", u->u_comm);
X
X if (f & CDIR)
X putchar ('c'); /* proc's current dir is on device */
X if (f & RDIR)
X putchar ('r'); /* proc's root dir is on device */
X if (f & OFILE)
X putchar ('f'); /* proc has file(s) open on device */
X printf ("\t");
X
X if (f & OFILE) /* list inodes of open file(s) */
X for (filen = 0; filen < NOFILE; filen++)
X if (inodes[filen] > 0)
X printf ("%d ", inodes[filen]);
X
X puts (""); /* silly way to print a newline */
X}
X
X
X/*
X * Check if file id matches stats we are searching for.
X */
X
Xcheck (filestats, fid)
Xstruct stat *filestats;
Xunion fileid *fid;
X{
X if (fid == NULL)
X return (0);
X
X if (ispecial (filestats->st_mode))
X {
X if (filestats->st_rdev == fid->special.dev
X && !strcmp (itype (filestats->st_mode), vtype (fid->special.type)))
X return (1); /* for special devices */
X else
X return (0);
X }
X
X if (filestats->st_dev == fid->file.fsid)
X {
X if (!inode) /* if we'll match any file */
X return (1);
X
X if (inode == fid->file.nodeid)
X return (1);
X#ifdef sun /* not sure I understand this */
X else if (fid->file.nodeid == 0)
X return (1);
X#endif
X }
X
X return (0);
X}
X
X/*
X * Read a vnode from /dev/kmem, return fileid (dev,ino).
X */
X
Xunion fileid *
Xgetfileid (node, s)
Xstruct vnode *node;
Xchar *s;
X{
X struct vnode v;
X static union xnode
X {
X struct inode i;
X struct rnode r;
X } x;
X
X union fileid fid;
X
X if (node == NULL)
X return (NULL);
X
X eseek (kmem, (long) node, 0, "vnode");
X eread (kmem, (char *) &v, sizeof (v), "vnode");
X
X if (vspecial (v.v_type))
X {
X fid.special.dev = v.v_rdev;
X fid.special.type = v.v_type;
X
X if (debug > 20)
X printf (" %s %s device %d/%d\n",
X s, vtype (v.v_type), major (v.v_rdev), minor (v.v_rdev));
X return (&fid);
X }
X
X if (debug > 20)
X printf (" %s %s", s, vtype (v.v_type));
X
X eseek (kmem, (long) v.v_data, 0, "inode/rnode");
X eread (kmem, (char *) &x, sizeof (x), "inode/rnode");
X
X if (x.r.r_nfsattr.na_type == v.v_type)
X { /* best test I could find for nfs */
X struct vfs vf;
X struct mntinfo mi;
X
X eseek (kmem, (long) v.v_vfsp, 0, "vfs");
X eread (kmem, (char *) &vf, sizeof (vf), "vfs");
X
X eseek (kmem, (long) vf.vfs_data, 0, "mntinfo");
X eread (kmem, (char *) &mi, sizeof (mi), "mntinfo");
X
X fid.file.fsid = makedev (0xff, mi.mi_mntno);
X fid.file.nodeid = x.r.r_nfsattr.na_nodeid;
X
X if (debug > 20)
X printf (" inode %d on nfs fs %x (%s)\n",
X x.r.r_nfsattr.na_nodeid, x.r.r_nfsattr.na_fsid,
X rtype (x.r.r_nfsattr.na_type));
X }
X else
X {
X fid.file.fsid = x.i.i_dev;
X fid.file.nodeid = x.i.i_number;
X
X if (debug > 20)
X printf (" inode %d on device %x (%s)\n",
X x.i.i_number, x.i.i_dev, itype (x.i.i_mode));
X }
X
X return (&fid);
X}
X
X
Xchar *
Xvtype (type)
Xenum vtype type;
X{
X switch (type)
X {
X case VNON:
X return ("none");
X case VREG:
X return ("file");
X case VDIR:
X return ("directory");
X case VBLK:
X return ("block special");
X case VCHR:
X return ("character special");
X case VLNK:
X return ("symbolic link");
X case VSOCK:
X return ("socket");
X case VBAD:
X return ("bad type");
X#ifdef S_IFIFO
X case VFIFO:
X return ("fifo");
X#endif
X default:
X return ("unknown vnode type");
X }
X}
X
Xchar *
Xrtype (type)
Xenum nfsftype type;
X{
X switch (type)
X {
X case NFNON:
X return ("none");
X case NFREG:
X return ("file");
X case NFDIR:
X return ("directory");
X case NFBLK:
X return ("block special");
X case NFCHR:
X return ("character special");
X case NFLNK:
X return ("symbolic link");
X default:
X return ("unknown");
X }
X}
X
Xchar *
Xitype (mode)
Xunsigned mode;
X{
X switch (mode & S_IFMT)
X {
X case S_IFREG:
X return ("file");
X case S_IFDIR:
X return ("directory");
X case S_IFBLK:
X return ("block special");
X case S_IFCHR:
X return ("character special");
X case S_IFLNK:
X return ("symbolic link");
X case S_IFSOCK:
X return ("socket");
X#ifdef S_IFIFO
X case S_IFIFO:
X return ("fifo");
X#endif
X default:
X return ("unknown inode type");
X }
X}
X
X/*
X * get user page for proc "p" from core or swap return pointer to user struct
X */
Xstruct user *
Xgetuser (p)
Xstruct proc *p;
X{
X struct pte *ptep;
X struct pte mypgtbl[UPAGES];
X int n,
X nbytes;
X char *up;
X static struct user user;
X
X /* easy way */
X if ((p->p_flag & SLOAD) == 0)
X {
X eseek (swap, (long) dtob (p->p_swaddr), 0, "user");
X if (read (swap, (char *) &user, sizeof (struct user)) <= 0)
X {
X if (debug)
X fprintf (stderr, "error: can't get swapped user page pid %d\n",
X p->p_pid);
X return (struct user *) NULL;
X }
X if (debug > 50)
X printf ("read swap\n");
X }
X else
X { /* boo */
X /* now get user page tbl */
X#ifdef sequent
X eseek (mem, p->p_upte, 0L, "user page table");
X if (read (mem, mypgtbl, sizeof (mypgtbl)) != sizeof (mypgtbl))
X {
X#else
X eseek (kmem, p->p_addr, 0L, "user page table");
X if (read (kmem, mypgtbl, sizeof (mypgtbl)) != sizeof (mypgtbl))
X {
X#endif
X if (debug)
X fprintf (stderr, "error: can't get mypgtbl pid %d\n",
X p->p_pid);
X return (struct user *) NULL;
X }
X /* now collect pages of u area */
X up = (char *) &user;
X ptep = mypgtbl;
X for (nbytes = sizeof (struct user); nbytes > 0; nbytes -= NBPG)
X {
X eseek (mem, ptep++->pg_pfnum * NBPG, 0L, "page table entry");
X n = MIN (nbytes, NBPG);
X if (read (mem, up, n) != n)
X {
X if (debug)
X fprintf (stderr, "cant get user tbl pid %d\n", p->p_pid);
X return (struct user *) NULL;
X }
X up += n;
X }
X }
X return &user;
X}
X
X
X/*
X * Get symbols from the kernel.
X */
X
Xgetsyms ()
X{
X register i;
X
X if (nlist (UNIX, nl))
X perror (UNIX), exit (1);
X
X for (i = 0; i < (sizeof (nl) / sizeof (nl[0])) - 1; i++)
X if (nl[i].n_value == 0)
X {
X fprintf (stderr, "%s: can't nlist for %s.\n",
X progname, nl[i].n_name);
X exit (1);
X }
X
X eseek (kmem, (long) nl[X_PROC].n_value, 0, "procbase");
X eread (kmem, &procbase, (unsigned) sizeof (procbase), "procbase");
X
X eseek (kmem, (long) nl[X_NPROC].n_value, 0, "nproc");
X eread (kmem, &nproc, sizeof (nproc), "nproc");
X
X /* variables used by <vmmac.h> */
X
X Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
X usrpt = (struct pte *) nl[X_USRPT].n_value;
X}
X
X
X/*
X * Read proc table entry "n" into buffer "p" .
X */
Xprocslot (n, p)
Xint n;
Xstruct proc *p;
X{
X eseek (kmem, procbase + (long) (n * sizeof (struct proc)), 0, "proc");
X eread (kmem, (char *) p, sizeof (struct proc), "proc");
X}
X
X/*
X * Read with error checking
X */
Xeread (fd, p, size, s)
Xint fd;
Xchar *p;
Xint size;
Xchar *s;
X{
X int n;
X char buf[100];
X if ((n = read (fd, p, size)) != size)
X {
X sprintf (buf, "read error for %s. ", s);
X error (buf);
X }
X return n;
X}
X
X/*
X * Seek with error checking
X */
X
Xlong
Xeseek (fd, off, whence, s)
Xint fd;
Xlong off;
Xint whence;
Xchar *s;
X{
X long lseek ();
X long ret;
X char buf[100];
X
X if ((ret = lseek (fd, off, whence)) != off)
X {
X sprintf (buf, "seek for %s failed, wanted %o, got %o. ",
X s, off, ret);
X error (buf);
X }
X return ret;
X}
//go.sysin dd *
exit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads