diff options
Diffstat (limited to 'dialects/sun/dfile.c')
-rw-r--r-- | dialects/sun/dfile.c | 669 |
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) */ |