summaryrefslogtreecommitdiff
path: root/dialects/sun/dfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'dialects/sun/dfile.c')
-rw-r--r--dialects/sun/dfile.c669
1 files changed, 669 insertions, 0 deletions
diff --git a/dialects/sun/dfile.c b/dialects/sun/dfile.c
new file mode 100644
index 0000000..bb09306
--- /dev/null
+++ b/dialects/sun/dfile.c
@@ -0,0 +1,669 @@
+/*
+ * dfile.c - Solaris file processing 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: dfile.c,v 1.21 2009/03/25 19:22:16 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local structures
+ */
+
+struct hsfile {
+ struct sfile *s; /* the Sfile table address */
+ struct hsfile *next; /* the next hash bucket entry */
+};
+
+
+/*
+ * Local static variables
+ */
+
+static struct hsfile *HbyCd = /* hash by clone buckets */
+ (struct hsfile *)NULL;
+static int HbyCdCt = 0; /* HbyCd entry count */
+static struct hsfile *HbyFdi = /* hash by file buckets */
+ (struct hsfile *)NULL;
+static int HbyFdiCt = 0; /* HbyFdi entry count */
+static struct hsfile *HbyFrd = /* hash by file raw device buckets */
+ (struct hsfile *)NULL;
+static int HbyFrdCt = 0; /* HbyFrd entry count */
+static struct hsfile *HbyFsd = /* hash by file system buckets */
+ (struct hsfile *)NULL;
+static int HbyFsdCt = 0; /* HbyFsd entry count */
+static struct hsfile *HbyNm = /* hash by name buckets */
+ (struct hsfile *)NULL;
+static int HbyNmCt = 0; /* HbyNm entry count */
+
+
+/*
+ * Local definitions
+ */
+
+#define SFCDHASH 1024 /* Sfile hash by clone device */
+#define SFDIHASH 4094 /* Sfile hash by (device,inode) number
+ * pair bucket count (power of 2!) */
+#define SFFSHASH 128 /* Sfile hash by file system device
+ * number bucket count (power of 2!) */
+#define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, and inode, modulo m
+ * (m must be a power of 2) */
+#define SFNMHASH 4096 /* Sfile hash by name bucket count
+ (power of 2!) */
+#define SFRDHASH 1024 /* Sfile hash by raw device number
+ * bucket count (power of 2!) */
+#define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, major raw device,
+ * minor raw device, and inode, modulo
+ * mod (mod must be a power of 2) */
+
+
+#if solaris<20500
+/*
+ * get_max_fd() - get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+ struct rlimit r;
+
+ if (getrlimit(RLIMIT_NOFILE, &r))
+ return(-1);
+ return(r.rlim_cur);
+}
+#endif /* solaris<20500 */
+
+
+/*
+ * hashSfile() - hash Sfile entries for use in is_file_named() searches
+ */
+
+void
+hashSfile()
+{
+ int cmaj, hvc, i;
+ static int hs = 0;
+ struct sfile *s;
+ struct hsfile *sh, *sn;
+/*
+ * Do nothing if there are no file search arguments cached or if the
+ * hashes have already been constructed.
+ */
+ if (!Sfile || hs)
+ return;
+/*
+ * Preset the clone major device for Solaris.
+ */
+ if (HaveCloneMaj) {
+ cmaj = CloneMaj;
+ hvc = 1;
+ } else
+ hvc = 0;
+/*
+ * Allocate hash buckets by clone device, (device,inode), file system device,
+ * and file name.
+ */
+ if (hvc) {
+ if (!(HbyCd = (struct hsfile *)calloc((MALLOC_S)SFCDHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d clone hash buckets\n",
+ Pn, SFCDHASH);
+ Exit(1);
+ }
+ }
+ if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d (dev,ino) hash buckets\n",
+ Pn, SFDIHASH);
+ Exit(1);
+ }
+ if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d rdev hash buckets\n",
+ Pn, SFRDHASH);
+ Exit(1);
+ }
+ if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d file sys hash buckets\n",
+ Pn, SFFSHASH);
+ Exit(1);
+ }
+ if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d name hash buckets\n",
+ Pn, SFNMHASH);
+ Exit(1);
+ }
+ hs++;
+/*
+ * Scan the Sfile chain, building file, file system, and file name hash
+ * bucket chains.
+ */
+ for (s = Sfile; s; s = s->next) {
+ for (i = 0; i < 4; i++) {
+ if (i == 0) {
+ if (!s->aname)
+ continue;
+ sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
+ HbyNmCt++;
+ } else if (i == 1) {
+ if (s->type) {
+ sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ s->i,
+ SFDIHASH)];
+ HbyFdiCt++;
+ } else {
+ sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ 0,
+ SFFSHASH)];
+ HbyFsdCt++;
+ }
+ } else if (i == 2) {
+ if (s->type
+ && ((s->mode == S_IFCHR) || (s->mode == S_IFBLK)))
+ {
+ sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ GET_MAJ_DEV(s->rdev),
+ GET_MIN_DEV(s->rdev),
+ s->i,
+ SFRDHASH)];
+ HbyFrdCt++;
+ } else
+ continue;
+ } else {
+ if (!hvc || (GET_MAJ_DEV(s->rdev) != cmaj))
+ continue;
+ sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0,
+ SFCDHASH)];
+ HbyCdCt++;
+ }
+ if (!sh->s) {
+ sh->s = s;
+ sh->next = (struct hsfile *)NULL;
+ continue;
+ } else {
+ if (!(sn = (struct hsfile *)malloc(
+ (MALLOC_S)sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate hsfile bucket for: %s\n",
+ Pn, s->aname);
+ Exit(1);
+ }
+ sn->s = s;
+ sn->next = sh->next;
+ sh->next = sn;
+ }
+ }
+ }
+}
+
+
+/*
+ * is_file_named() - is this file named?
+ */
+
+int
+is_file_named(p, nt, vt, ps)
+ char *p; /* path name; NULL = search by device
+ * and inode (from *Lf) */
+ int nt; /* node type -- e.g., N_* */
+ enum vtype vt; /* vnode type */
+ int ps; /* print status: 0 = don't copy name
+ * to Namech */
+{
+ char *ep;
+ int f = 0;
+ struct sfile *s;
+ struct hsfile *sh;
+ size_t sz;
+/*
+ * Check for a path name match, as requested.
+ */
+ if (p && HbyNmCt) {
+ for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) {
+ if ((s = sh->s) && strcmp(p, s->aname) == 0) {
+ f = 2;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a Solaris clone file.
+ */
+ if (!f && HbyCdCt && nt == N_STREAM && Lf->dev_def && Lf->rdev_def
+ && (Lf->dev == DevDev))
+ {
+ for (sh = &HbyCd[SFHASHDEVINO(0, GET_MAJ_DEV(Lf->rdev), 0,
+ SFCDHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (GET_MAJ_DEV(Lf->rdev)
+ == GET_MIN_DEV(s->rdev)))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a regular file.
+ */
+ if (!f && HbyFdiCt && Lf->dev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev),
+ Lf->inode,
+ SFDIHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (Lf->dev == s->dev)
+ && (Lf->inode == s->i)) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a file system match.
+ */
+ if (!f && HbyFsdCt && Lf->dev_def) {
+ for (sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev), 0, SFFSHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && Lf->dev == s->dev) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a character or block device match.
+ */
+ if (!f && HbyFrdCt
+ && ((vt = VCHR) || (vt = VBLK))
+ && Lf->dev_def && (Lf->dev == DevDev)
+ && Lf->rdev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev),
+ GET_MAJ_DEV(Lf->rdev),
+ GET_MIN_DEV(Lf->rdev),
+ Lf->inode, SFRDHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (s->dev == Lf->dev)
+ && (s->rdev == Lf->rdev) && (s->i == Lf->inode))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Convert the name if a match occurred.
+ */
+ if (f) {
+ if (f == 2) {
+ if (ps)
+ (void) snpf(Namech, Namechl, "%s", p);
+ } else {
+ if (ps && s->type) {
+
+ /*
+ * If the search argument isn't a file system, propagate it
+ * to Namech[]; otherwise, let printname() compose the name.
+ */
+ (void) snpf(Namech, Namechl, "%s", s->name);
+ if (s->devnm) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, " (%s)", s->devnm);
+ }
+ }
+ }
+ s->f = 1;
+ return(1);
+ }
+ return(0);
+}
+
+
+#if defined(HASPRINTDEV)
+/*
+ * print_dev() - print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+/*
+ * Avoid the Solaris major() and minor() functions from makedev(3C) to get
+ * printable major/minor numbers.
+ *
+ * We would like to use the L_MAXMAJ definition from <sys/sysmacros.h> all
+ * the time, but it's not always correct in all versions of Solaris.
+ */
+ (void) snpf(buf, sizeof(buf), "%d,%d", (int)((*dev >> L_BITSMINOR) &
+
+#if solaris>=20501
+ L_MAXMAJ
+#else /* solaris<20501 */
+ 0x3fff
+#endif /* solaris>=20501 */
+
+ ), (int)(*dev & L_MAXMIN));
+ return(buf);
+}
+#endif /* defined(HASPRINTDEV) */
+
+
+#if defined(HAS_V_PATH)
+
+/*
+ * Local definitions
+ */
+
+#define VPRDLEN ((MAXPATHLEN + 7)/8) /* v_path read length increment */
+
+
+/*
+ * print_v_path() - print path name from vnode's v_path pointer
+ */
+
+extern int
+print_v_path(lf)
+ struct lfile *lf; /* local file structure */
+{
+ char buf[MAXPATHLEN+1];
+ unsigned char del = 0;
+ unsigned char aperr = 0;
+
+# if defined(HASMNTSTAT)
+ struct stat sb;
+# endif /* defined(HASMNTSTAT) */
+
+# if defined(HASVXFS) && defined(HASVXFSRNL)
+ if (lf->is_vxfs && (lf->inp_ty == 1) && lf->fsdir) {
+ if (print_vxfs_rnl_path(lf))
+ return(1);
+ }
+# endif /* defined(HASVXFS) && defined(HASVXFSRNL) */
+
+ (void) read_v_path((KA_T)lf->V_path, buf, (size_t)sizeof(buf));
+ if (buf[0]) {
+
+# if defined(HASMNTSTAT)
+ if (!lf->mnt_stat && lf->dev_def && (lf->inp_ty == 1)) {
+
+ /*
+ * No problem was detected in applying stat(2) to this mount point.
+ * If the device and inode for the file are known, it is probably
+ * safe and worthwhile to apply stat(2) to the v_path.
+ */
+ if (!statsafely(buf, &sb)) {
+
+ /*
+ * The stat(2) succeeded. See if the device and inode match.
+ * If they both don't match, ignore the v_path.
+ */
+ if ((lf->dev != sb.st_dev)
+ || (lf->inode != (INODETYPE)sb.st_ino)
+ ) {
+ return(0);
+ }
+ } else {
+
+ /*
+ * The stat(2) failed.
+ *
+ * If the error reply is ENOENT and the -X option hasn't been
+ * specified, ignore the v_path.
+ *
+ * If the error reply is ENOENT, the -X option has been
+ * specified and the file's link count is zero, report the
+ * v_path with the "(deleted)" notation.
+ *
+ * If the error reply is EACCES or EPERM, report the v_path,
+ * followed by "(?)", because lsof probably lacks permission
+ * to apply stat(2) to v_path.
+ */
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ aperr = 1;
+ break;
+ case ENOENT:
+
+# if defined(HASXOPT)
+ if (Fxopt && lf->nlink_def && !lf->nlink) {
+ del = 1;
+ break;
+ }
+# endif /* defined(HASXOPT) */
+
+ return(0);
+ default:
+ return(0);
+ }
+ }
+ }
+# endif /* defined(HASMNTSTAT) */
+
+ /*
+ * Print the v_path.
+ */
+ safestrprt(buf, stdout, 0);
+ if (del)
+ safestrprt(" (deleted)", stdout, 0);
+ else if (aperr)
+ safestrprt(" (?)", stdout, 0);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_v_path() - read path name from vnode's v_path pointer
+ */
+
+extern void
+read_v_path(ka, rb, rbl)
+ KA_T ka; /* kernel path address */
+ char *rb; /* receiving buffer */
+ size_t rbl; /* receiving buffer length */
+{
+ char *ba;
+ size_t rl, tl;
+
+ *rb = '\0';
+ if (!ka)
+ return;
+ for (ba = rb, tl = 0;
+ tl < (rbl - 1);
+ ba += rl, ka += (KA_T)((char *)ka + rl), tl += rl
+ ) {
+
+ /*
+ * Read v_path VPRDLEN bytes at a time until the local buffer is full
+ * or a NUL byte is reached.
+ */
+ if ((rl = rbl - 1 - tl) > VPRDLEN)
+ rl = VPRDLEN;
+ else if (rl < 1) {
+ *(rb + rbl - 1) = '\0';
+ break;
+ }
+ if (!kread(ka, ba, rl)) {
+ *(ba + rl) = '\0';
+ if (strchr(ba, '\0') < (ba + rl))
+ break;
+ } else {
+
+ /*
+ * Can't read a full buffer load; try reducing the length one
+ * byte at a time until it reaches zero. Stop here, since it
+ * has been established that no more bytes can be read.
+ */
+ for (rl--; rl > 0; rl--) {
+ if (!kread(ka, ba, rl)) {
+ *(ba + rl) = '\0';
+ break;
+ }
+ }
+ if (rl <= 0)
+ *ba = '\0';
+ break;
+ }
+ }
+}
+#endif /* defined(HAS_V_PATH) */
+
+
+/*
+ * process_file() - process file
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+ struct file f;
+ int flag;
+
+#if defined(FILEPTR)
+ FILEPTR = &f;
+#endif /* defined(FILEPTR) */
+
+ if (kread(fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Lf->off = (SZOFFTYPE)f.f_offset;
+
+ if (f.f_count) {
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_vnode;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Solaris file structures contain a vnode pointer. Process it.
+ */
+ process_node((KA_T)f.f_vnode);
+ return;
+ }
+ enter_nm("no more information"); }
+
+
+#if defined(HASIPv6)
+/*
+ * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function
+ * to get AF_INET and AF_INET6 addresses from host names,
+ * using the RFC2553-compatible getipnodebyname() function
+ */
+
+extern struct hostent *
+gethostbyname2(nm, prot)
+ const char *nm; /* host name */
+ int prot; /* protocol -- AF_INET or AF_INET6 */
+{
+ int err;
+ static struct hostent *hep = (struct hostent *)NULL;
+
+ if (hep)
+ (void) freehostent(hep);
+ return((hep = getipnodebyname(nm, prot, 0, &err)));
+}
+#endif /* defined(HASIPv6) */