summaryrefslogtreecommitdiff
path: root/lib/isfn.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isfn.c')
-rw-r--r--lib/isfn.c418
1 files changed, 418 insertions, 0 deletions
diff --git a/lib/isfn.c b/lib/isfn.c
new file mode 100644
index 0000000..b23846d
--- /dev/null
+++ b/lib/isfn.c
@@ -0,0 +1,418 @@
+/*
+ * isfn.c -- is_file_named() function for lsof library
+ */
+
+
+/*
+ * Copyright 1997 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.
+ */
+
+
+/*
+ * To use this source file:
+ *
+ * 1. Define USE_LIB_IS_FILE_NAMED.
+ *
+ * 2. If clone support is required:
+ *
+ * a. Define HAVECLONEMAJ to be the name of the variable that
+ * contains the status of the clone major device -- e.g.,
+ *
+ * #define HAVECLONEMAJ HaveCloneMaj
+ *
+ * b. Define CLONEMAJ to be the name of the constant or
+ * variable that defines the clone major device -- e.g.,
+ *
+ * #define CLONEMAJ CloneMaj
+ *
+ * c. Make sure that clone devices are identified by an lfile
+ * element is_stream value of 1.
+ *
+ * d. Accept clone searching by device number only.
+ */
+
+
+#include "../machine.h"
+
+#if defined(USE_LIB_IS_FILE_NAMED)
+
+# if !defined(lint)
+static char copyright[] =
+"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: isfn.c,v 1.10 2008/10/21 16:12:36 abe Exp $";
+# endif /* !defined(lint) */
+
+#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
+ */
+
+# if defined(HAVECLONEMAJ)
+static struct hsfile *HbyCd = /* hash by clone buckets */
+ (struct hsfile *)NULL;
+static int HbyCdCt = 0; /* HbyCd entry count */
+# endif /* defined(HAVECLONEMAJ) */
+
+static struct hsfile *HbyFdi = /* hash by file (dev,ino) 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
+ */
+
+# if defined(HAVECLONEMAJ)
+#define SFCDHASH 1024 /* Sfile hash by clone device (power
+ * of 2!) */
+# endif /* defined(HAVECLONEMAJ) */
+
+#define SFDIHASH 4094 /* Sfile hash by (device,inode) number
+ * pair bucket count (power of 2!) */
+#define SFFSHASH 1024 /* 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 mod
+ * (mod must be a 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) */
+#define SFNMHASH 4096 /* Sfile hash by name bucket count
+ * (must be a power of 2!) */
+
+
+
+/*
+ * hashSfile() - hash Sfile entries for use in is_file_named() searches
+ */
+
+void
+hashSfile()
+{
+ static int hs = 0;
+ int i;
+ int sfplm = 3;
+ 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;
+/*
+ * Allocate hash buckets by (device,inode), file system device, and file name.
+ */
+
+# if defined(HAVECLONEMAJ)
+ if (HAVECLONEMAJ) {
+ 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);
+ }
+ sfplm++;
+ }
+# endif /* defined(HAVECLONEMAJ) */
+
+ 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, raw device, and file
+ * name hash bucket chains.
+ */
+ for (s = Sfile; s; s = s->next) {
+ for (i = 0; i < sfplm; 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->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;
+ }
+
+# if defined(HAVECLONEMAJ)
+ else {
+ if (!HAVECLONEMAJ || (GET_MAJ_DEV(s->rdev) != CLONEMAJ))
+ continue;
+ sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0,
+ SFCDHASH)];
+ HbyCdCt++;
+ }
+# else /* ! defined(HAVECLONEMAJ) */
+ else
+ continue;
+# endif /* defined(HAVECLONEMAJ) */
+
+ 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, cd)
+ char *p; /* path name; NULL = search by device
+ * and inode (from *Lf) */
+ int cd; /* character or block type file --
+ * VCHR or VBLK vnode, or S_IFCHR
+ * or S_IFBLK inode */
+{
+ char *ep;
+ int f = 0;
+ struct sfile *s = (struct sfile *)NULL;
+ 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;
+ }
+ }
+ }
+
+# if defined(HAVECLONEMAJ)
+/*
+ * If this is a stream, check for a clone device match.
+ */
+ if (!f && HbyCdCt && Lf->is_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 = 3;
+ break;
+ }
+ }
+ }
+# endif /* defined(HAVECLONEMAJ) */
+
+/*
+ * 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) && (s->dev == Lf->dev)) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a character or block device match.
+ */
+ if (!f && HbyFrdCt && cd
+ && 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.
+ */
+ switch (f) {
+ case 0:
+ return(0);
+ case 1:
+ if (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);
+ }
+ }
+ break;
+ case 2:
+ (void) strcpy(Namech, p);
+ break;
+
+# if defined(HAVECLONEMAJ)
+ /* case 3: do nothing for stream clone matches */
+# endif /* defined(HAVECLONEMAJ) */
+
+ }
+ if (s)
+ s->f = 1;
+ return(1);
+}
+#else /* !defined(USE_LIB_IS_FILE_NAMED) */
+char isfn_d1[] = "d"; char *isfn_d2 = isfn_d1;
+#endif /* defined(USE_LIB_IS_FILE_NAMED) */