diff options
Diffstat (limited to 'dialects/sun/dmnt.c')
-rw-r--r-- | dialects/sun/dmnt.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/dialects/sun/dmnt.c b/dialects/sun/dmnt.c new file mode 100644 index 0000000..c9c023c --- /dev/null +++ b/dialects/sun/dmnt.c @@ -0,0 +1,417 @@ +/* + * dmnt.c - Solaris mount support 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: dmnt.c,v 1.15 2005/08/29 10:24:25 abe Exp $"; +#endif + + +#include "lsof.h" + + +/* + * Local static definitions + */ + +static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ +static int Lmist = 0; /* Lmi status */ + + +_PROTOTYPE(static char *getmntdev,(char *o, int l, struct stat *s, char *f)); + + +/* + * getmntdev() - get mount entry's device number + */ + +static char * +getmntdev(o, l, s, f) + char *o; /* start of device option */ + int l; /* length of device keyword (not + * including `=') */ + struct stat *s; /* pointer to stat buffer to create */ + char *f; /* file system type */ +{ + char *opte; + + memset((char *)s, 0, sizeof(struct stat)); + if (!(opte = x2dev(o + l + 1, &s->st_dev))) + return((char *)NULL); + +#if solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32 +/* + * If this is a Solaris 7 system with a 64 bit kernel, convert the 32 bit + * device number to a 64 bit device number. + */ + s->st_dev = (((s->st_dev >> L_BITSMINOR32) & L_MAXMAJ32) << L_BITSMINOR) + | (s->st_dev & L_MAXMIN32); +#endif /* solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32 */ + + s->st_mode = S_IFDIR | 0777; + +#if defined(HASFSTYPE) + if (f) { + (void) strncpy(s->st_fstype, f, sizeof(s->st_fstype)); + s->st_fstype[sizeof(s->st_fstype) - 1] = '\0'; + } +#endif /* defined(HASFSTYPE) */ + + return(opte); +} + + +/* + * readmnt() - read mount table + */ + +struct mounts * +readmnt() +{ + int devl, ignore; + char *cp, *dir, *fs; + char *dn = (char *)NULL; + char *ln; + FILE *mfp; + struct mounts *mtp; + char *dopt, *dopte; + struct stat sb; + struct mnttab me; + struct mnttab *mp; + +#if defined(HASPROCFS) + int procfs = 0; +#endif /* defined(HASPROCFS) */ + + unsigned char stat; + char *zopt; + +#if defined(HASZONES) + int zwarn = 0; +#endif /* definesd(HASZONES) */ + + if (Lmi || Lmist) + return(Lmi); + devl = strlen(MNTOPT_DEV); +/* + * Open access to the mount table and read mount table entries. + */ + if (!(mfp = fopen(MNTTAB, "r"))) { + (void) fprintf(stderr, "%s: can't access %s\n", Pn, MNTTAB); + return(0); + } + for (mp = &me; getmntent(mfp, mp) == 0;) { + + /* + * Skip loop-back mounts, since they are aliases for legitimate file + * systems and there is no way to determine that a vnode refers to a + * loop-back alias. + */ + if (strcmp(mp->mnt_fstype, MNTTYPE_LO) == 0) + continue; + /* + * Save pointers to the directory and file system names for later use. + * + * Check the file system name. If it doesn't begin with a `/' + * but contains a `:' not followed by a '/', ignore this entry. + */ + dir = mp->mnt_mountp; + fs = mp->mnt_special; + if (*fs != '/' && (cp = strchr(fs, ':')) && *(cp+1) != '/') + continue; + /* + * Check for a "ignore" type (SunOS) or "ignore" option (Solaris). + */ + if (hasmntopt(mp, MNTOPT_IGNORE)) + ignore = 1; + else + ignore = 0; + /* + * Interpolate a possible symbolic directory link. + */ + if (dn) + (void) free((FREE_P *)dn); + if (!(dn = mkstrcpy(dir, (MALLOC_S *)NULL))) { + +no_space_for_mount: + + (void) fprintf(stderr, "%s: no space for mount ", Pn); + safestrprt(fs, stderr, 0); + (void) fprintf(stderr, " ("); + safestrprt(dir, stderr, 0); + (void) fprintf(stderr, ")\n"); + Exit(1); + } + if (!(ln = Readlink(dn))) { + if (!Fwarn) { + (void) fprintf(stderr, + " Output information may be incomplete.\n"); + } + continue; + } + if (ln != dn) { + (void) free((FREE_P *)dn); + dn = ln; + } + if (*dn != '/') + continue; + /* + * Stat() the directory. + * + * Avoid the stat() if the mount entry has an "ignore" option and + * try to use the mount entry's device number instead. + */ + dopt = hasmntopt(mp, MNTOPT_DEV); + if (ignore) { + if (!dopt + || !(dopte = getmntdev(dopt, devl, &sb, + +#if defined(HASFSTYPE) + mp->mnt_fstype +#else /* !defined(HASFSTYPE) */ + (char *)NULL +#endif /* defined(HASFSTYPE) */ + + )) + ) + continue; + stat = 1; + } else if (statsafely(dn, &sb)) { + if (dopt) { + if (!(dopte = getmntdev(dopt, devl, &sb, + +#if defined(HASFSTYPE) + mp->mnt_fstype +#else /* !defined(HASFSTYPE) */ + (char *)NULL +#endif /* defined(HASFSTYPE) */ + + )) + ) + dopt = (char *)NULL; + } else + dopte = (char *)NULL; + if (!Fwarn) { + +#if defined(HASZONES) + if ((zopt = hasmntopt(mp, "zone")) && dopte) + zwarn++; +#else /* !defined(HASZONES) */ + zopt = (char *)NULL; +#endif /* defined(HASZONES) */ + + if (!zopt || !dopte) { + (void) fprintf(stderr, + "%s: WARNING: can't stat() ", Pn); + safestrprt(mp->mnt_fstype, stderr, 0); + (void) fprintf(stderr, " file system "); + safestrprt(dir, stderr, 1); + (void) fprintf(stderr, + " Output information may be incomplete.\n"); + if (dopte) { + (void) fprintf(stderr, + " assuming \"%.*s\" from %s\n", + (int)(dopte - dopt), dopt, MNTTAB); + } + } + } + if (!dopt) + continue; + stat = 1; + } else + stat = 0; + /* + * Allocate and fill a local mount structure. + */ + if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) + goto no_space_for_mount; + +#if defined(HASFSTYPE) + if (!(mtp->fstype = mkstrcpy(sb.st_fstype, (MALLOC_S *)NULL))) + goto no_space_for_mount; +#endif /* defined(HASFSTYPE) */ + + mtp->dir = dn; + dn = (char *)NULL; + mtp->next = Lmi; + mtp->dev = sb.st_dev; + mtp->rdev = sb.st_rdev; + mtp->inode = (INODETYPE)sb.st_ino; + mtp->mode = sb.st_mode; + +#if solaris>=80000 + mtp->nlink = sb.st_nlink; + mtp->size = sb.st_size; +#endif /* solaris>=80000 */ + +#if defined(HASMNTSTAT) + mtp->stat = stat; +#endif /* defined(HASMNTSTAT) */ + +#if defined(HASPROCFS) + if (strcmp(sb.st_fstype, HASPROCFS) == 0) { + + /* + * Save information on exactly one proc file system. + */ + if (procfs) + Mtprocfs = (struct mounts *)NULL; + else { + procfs = 1; + Mtprocfs = mtp; + } + } +#endif /* defined(HASPROCFS) */ + + /* + * Interpolate a possible file system (mounted-on) device name link. + */ + if (!(dn = mkstrcpy(fs, (MALLOC_S *)NULL))) + goto no_space_for_mount; + mtp->fsname = dn; + ln = Readlink(dn); + dn = (char *)NULL; + /* + * Stat() the file system (mounted-on) name and add file system + * information to the local mount table entry. + */ + if (!ln || statsafely(ln, &sb)) + sb.st_mode = 0; + mtp->fsnmres = ln; + mtp->fs_mode = sb.st_mode; + Lmi = mtp; + +#if defined(HAS_AFS) + /* + * If an AFS device number hasn't yet been defined, look for it. + */ + if (!AFSdevStat + && mtp->dir && strcmp(mtp->dir, "/afs") == 0 + && mtp->fsname && strcmp(mtp->fsname, "AFS") == 0) { + AFSdev = mtp->dev; + AFSdevStat = 1; + } +#endif /* defined(HAS_AFS) && solaris>=20600 */ + + } + (void) fclose(mfp); + +#if defined(HASZONES) +/* + * If some zone file systems were encountered, issue a warning. + */ + if (!Fwarn && zwarn) { + (void) fprintf(stderr, + "%s: WARNING: can't stat() %d zone file system%s", Pn, zwarn, + (zwarn == 1) ? "" : "s"); + (void) fprintf(stderr, "; using dev= option%s\n", + (zwarn == 1) ? "" : "s"); + } +#endif /* defined(HASZONES) */ + +/* + * Clean up and return local mount info table address. + */ + if (dn) + (void) free((FREE_P *)dn); + Lmist = 1; + return(Lmi); +} + + +/* + * readvfs() - read vfs structure + */ + +struct l_vfs * +readvfs(ka, la, lv) + KA_T ka; /* vfs structure kernel address, if + * must be read from kernel */ + struct vfs *la; /* local vfs structure address, non- + * NULL if already read from kernel */ + struct vnode *lv; /* local vnode */ +{ + struct vfs *v, tv; + struct l_vfs *vp; + + if (!ka && !la) + return((struct l_vfs *)NULL); + for (vp = Lvfs; vp; vp = vp->next) { + if (ka == vp->addr) + return(vp); + } + if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { + (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", + Pn, Lp->pid); + Exit(1); + } + vp->dir = (char *)NULL; + vp->fsname = (char *)NULL; + +#if defined(HASFSINO) + vp->fs_ino = 0; +#endif /* defined(HASFSINO) */ + +/* + * Read vfs structure from kernel, if necessary. + */ + if (la) + v = la; + else { + v = &tv; + if (kread((KA_T)ka, (char *)v, sizeof(tv))) { + (void) free((FREE_P *)vp); + return((struct l_vfs *)NULL); + } + } + +#if defined(HAS_AFS) +/* + * Fake the device number for an AFS device. + */ + if (v->vfs_fstype == AFSfstype) { + if (!AFSdevStat) + (void) readmnt(); + v->vfs_dev = AFSdevStat ? AFSdev : 0; + } +#endif /* defined(HAS_AFS) */ + +/* + * Complete mount information. + */ + + (void) completevfs(vp, (dev_t *)&v->vfs_dev); + vp->next = Lvfs; + vp->addr = ka; + Lvfs = vp; + return(vp); +} |