| /* |
| * dmnt.c - AIX 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.13 2005/08/08 19:46:38 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 */ |
| |
| |
| /* |
| * readmnt() - read mount table |
| */ |
| |
| struct mounts * |
| readmnt() |
| { |
| char *dir, *fs, *h, *ln, *ty; |
| char *dn = (char *)NULL; |
| struct mounts *mtp; |
| int nm; |
| struct stat sb; |
| MALLOC_S sz; |
| struct vmount *v; |
| struct vmount *vt = (struct vmount *)NULL; |
| |
| if (Lmi || Lmist) |
| return(Lmi); |
| /* |
| * Read the table of vmount structures. |
| */ |
| for (sz = sizeof(struct vmount);;) { |
| if (!(vt = (struct vmount *)malloc(sz))) { |
| (void) fprintf(stderr, "%s: no space for vmount table\n", Pn); |
| return(0); |
| } |
| nm = mntctl(MCTL_QUERY, sz, (unsigned char *)vt); |
| if (nm > 0) { |
| if (vt->vmt_revision != VMT_REVISION) { |
| (void) fprintf(stderr, |
| "%s: stale file system, rev %d != %d\n", |
| Pn, vt->vmt_revision, VMT_REVISION); |
| return(0); |
| } |
| break; |
| } |
| if (nm == 0) { |
| sz = (unsigned)vt->vmt_revision; |
| (void) free((FREE_P *)vt); |
| } else { |
| (void) fprintf(stderr, "%s: mntctl error: %s\n", |
| Pn, strerror(errno)); |
| return(0); |
| } |
| } |
| /* |
| * Scan the vmount structures and build Lmi. |
| */ |
| for (v = vt; nm--; v = (struct vmount *)((char *)v + v->vmt_length)) { |
| dir = (char *)vmt2dataptr(v, VMT_STUB); |
| fs = (char *)vmt2dataptr(v, VMT_OBJECT); |
| h = (char *)vmt2dataptr(v, VMT_HOST); |
| if (statsafely(dir, &sb)) { |
| if (!Fwarn) { |
| |
| /* |
| * Issue stat() failure warning. |
| */ |
| switch(v->vmt_gfstype) { |
| |
| #if defined(HAS_AFS) |
| case MNT_AFS: |
| ty = "afs"; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if defined(MNT_AIX) && defined(MNT_J2) && MNT_AIX==MNT_J2 |
| case MNT_AIX: |
| ty = "jfs2"; |
| break; |
| #else /* !defined(MNT_AIX) || !defined(MNT_J2) || MNT_AIX!=MNT_J2 */ |
| # if defined(MNT_AIX) |
| case MNT_AIX: |
| ty = "oaix"; |
| break; |
| # endif /* defined(MNT_AIX) */ |
| # if defined(MNT_J2) |
| case MNT_J2: |
| ty = "jfs2"; |
| break; |
| # endif /* defined(MNT_J2) */ |
| #endif /* defined(MNT_AIX) && defined(MNT_H2) && MNT_AIX==MNT_J2 */ |
| |
| case MNT_CDROM: |
| ty = "cdrom"; |
| break; |
| case MNT_JFS: |
| ty = "jfs"; |
| break; |
| case MNT_NFS: |
| ty = "nfs"; |
| break; |
| |
| #if defined(MNT_NFS3) |
| case MNT_NFS3: |
| ty = "nfs3"; |
| break; |
| #endif /* defined(MNT_NFS3) */ |
| |
| #if defined(HASPROCFS) |
| case MNT_PROCFS: |
| ty = HASPROCFS; |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| #if defined(MNT_SANFS) |
| case MNT_SANFS: |
| ty = "sanfs"; |
| break; |
| #endif /* defined(MNT_SANFS) */ |
| |
| default: |
| ty = "unknown"; |
| } |
| (void) fprintf(stderr, |
| "%s: WARNING: can't stat() %s file system %s\n", |
| Pn, ty, dir); |
| (void) fprintf(stderr, |
| " Output information may be incomplete.\n"); |
| } |
| /* |
| * Assemble alternate device number and mode flags. |
| */ |
| (void) bzero((char *)&sb, sizeof(sb)); |
| if (v->vmt_flags & MNT_REMOTE) { |
| |
| #if AIXA<2 |
| sb.st_dev = (dev_t)(SDEV_REMOTE | v->vmt_vfsnumber); |
| #else /* AIXA>=2 */ |
| sb.st_dev = (dev_t)(SDEV_REMOTE | (SDEV_REMOTE << 32) |
| | v->vmt_vfsnumber); |
| #endif /* AIXA<2 */ |
| |
| } else { |
| |
| #if defined(HAS_AFS) |
| if (v->vmt_gfstype == MNT_AFS) |
| sb.st_dev = AFSDEV; |
| else |
| #endif /* defined(HAS_AFS) */ |
| |
| #if AIXA>=2 && defined(HASPROCFS) |
| if (v->vmt_gfstype == MNT_PROCFS) { |
| |
| /* |
| * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! |
| * |
| * The following *hack* is required to make the vmount |
| * structure's device number match what stat(2) |
| * errnoneously returns on ia64 AIX 5L. |
| * |
| * REMOVE THIS CODE WHEN STAT(2) IS FIXED!!! |
| */ |
| sb.st_dev = (dev_t)(v->vmt_fsid.val[0] |
| & 0x7fffffffffffffff); |
| /* |
| * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! |
| */ |
| |
| } |
| else |
| #endif /* AIXA>=2 && defined(HASPROCFS) */ |
| |
| sb.st_dev = (dev_t)v->vmt_fsid.val[0]; |
| } |
| if (!Fwarn) |
| (void) fprintf(stderr, |
| " assuming \"dev=%#lx\" from mount table\n", |
| sb.st_dev); |
| sb.st_mode = S_IFDIR | 0777; |
| } |
| /* |
| * Allocate space for the directory (mounted on) and resolve |
| * any symbolic links. |
| */ |
| 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 at %s (%s)\n", |
| Pn, fs, dir); |
| 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; |
| /* |
| * Allocate a local mounts structure and fill the directory information. |
| */ |
| if (!(mtp = (struct mounts *)malloc( |
| (MALLOC_S)sizeof(struct mounts)))) |
| goto no_space_for_mount; |
| mtp->dir = dn; |
| dn = (char *)NULL; |
| mtp->dev = sb.st_dev; |
| mtp->inode = (INODETYPE)sb.st_ino; |
| mtp->mode = sb.st_mode; |
| mtp->rdev = sb.st_rdev; |
| |
| #if defined(HASFSTYPE) |
| mtp->fstype = sb.st_vfstype; |
| #endif /* defined(HASFSTYPE) */ |
| |
| mtp->next = Lmi; |
| /* |
| * Form the file system (mounted-on) device name. Resolve any |
| * symbolic links. Allocate space for the result and store it in |
| * the local mounts structure. |
| */ |
| if (h && (v->vmt_flags & MNT_REMOTE)) { |
| if (!(dn = mkstrcat(h, -1, *h ? ":" : "", 1, fs, -1, |
| (MALLOC_S *)NULL))) |
| goto no_space_for_mount; |
| } else { |
| 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) device name to get its modes. |
| * Set the modes to zero if the stat fails. Add file system |
| * (mounted-on) device information to the local mountsstructure. |
| */ |
| if (!ln || statsafely(ln, &sb)) |
| sb.st_mode = 0; |
| mtp->fsnmres = ln; |
| mtp->fs_mode = sb.st_mode; |
| Lmi = mtp; |
| } |
| /* |
| * Clean up and return local mount info table address. |
| */ |
| if (dn) |
| (void) free((FREE_P *)dn); |
| if (vt) |
| (void) free((FREE_P *)vt); |
| Lmist = 1; |
| return(Lmi); |
| } |