1/* 2 * dmnt.c - Darwin mount support functions for /dev/kmem-based lsof 3 */ 4 5 6/* 7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana 8 * 47907. All rights reserved. 9 * 10 * Written by Victor A. Abell 11 * 12 * This software is not subject to any license of the American Telephone 13 * and Telegraph Company or the Regents of the University of California. 14 * 15 * Permission is granted to anyone to use this software for any purpose on 16 * any computer system, and to alter it and redistribute it freely, subject 17 * to the following restrictions: 18 * 19 * 1. Neither the authors nor Purdue University are responsible for any 20 * consequences of the use of this software. 21 * 22 * 2. The origin of this software must not be misrepresented, either by 23 * explicit claim or by omission. Credit to the authors and Purdue 24 * University must appear in documentation and sources. 25 * 26 * 3. Altered versions must be plainly marked as such, and must not be 27 * misrepresented as being the original software. 28 * 29 * 4. This notice may not be removed or altered. 30 */ 31 32#ifndef lint 33static char copyright[] = 34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; 35static char *rcsid = "$Id: dmnt.c,v 1.4 2005/11/01 20:24:51 abe Exp $"; 36#endif 37 38 39#include "lsof.h" 40 41 42/* 43 * Local static information 44 */ 45 46static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ 47static int Lmist = 0; /* Lmi status */ 48 49/* 50 * readmnt() - read mount table 51 */ 52 53struct mounts * 54readmnt() 55{ 56 char *dn = (char *)NULL; 57 char *ln; 58 struct statfs *mb = (struct statfs *)NULL; 59 struct mounts *mtp; 60 int n; 61 struct stat sb; 62 63 if (Lmi || Lmist) 64 return(Lmi); 65/* 66 * Access mount information. 67 */ 68 if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { 69 (void) fprintf(stderr, "%s: no mount information\n", Pn); 70 return(0); 71 } 72/* 73 * Read mount information. 74 */ 75 for (; n; n--, mb++) { 76 77 if (!mb->f_type) 78 continue; 79 /* 80 * Interpolate a possible symbolic directory link. 81 */ 82 if (dn) 83 (void) free((FREE_P *)dn); 84 if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { 85 86no_space_for_mount: 87 88 (void) fprintf(stderr, "%s: no space for mount at ", Pn); 89 safestrprt(mb->f_mntonname, stderr, 0); 90 (void) fprintf(stderr, " ("); 91 safestrprt(mb->f_mntfromname, stderr, 0); 92 (void) fprintf(stderr, ")\n"); 93 Exit(1); 94 } 95 if (!(ln = Readlink(dn))) { 96 if (!Fwarn) { 97 (void) fprintf(stderr, 98 " Output information may be incomplete.\n"); 99 } 100 continue; 101 } 102 if (ln != dn) { 103 (void) free((FREE_P *)dn); 104 dn = ln; 105 } 106 if (*dn != '/') 107 continue; 108 /* 109 * Stat() the directory. 110 */ 111 if (statsafely(dn, &sb)) { 112 if (!Fwarn) { 113 (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); 114 115 safestrprt(mb->f_fstypename, stderr, 0); 116 117 (void) fprintf(stderr, " file system "); 118 safestrprt(mb->f_mntonname, stderr, 1); 119 (void) fprintf(stderr, 120 " Output information may be incomplete.\n"); 121 } 122 (void) bzero((char *)&sb, sizeof(sb)); 123 sb.st_dev = (dev_t)mb->f_fsid.val[0]; 124 sb.st_mode = S_IFDIR | 0777; 125 if (!Fwarn) { 126 (void) fprintf(stderr, 127 " assuming \"dev=%x\" from mount table\n", 128 sb.st_dev); 129 } 130 } 131 /* 132 * Allocate and fill a local mount structure. 133 */ 134 if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) 135 goto no_space_for_mount; 136 mtp->dir = dn; 137 dn = (char *)NULL; 138 139 mtp->next = Lmi; 140 mtp->dev = sb.st_dev; 141 mtp->rdev = sb.st_rdev; 142 mtp->inode = (INODETYPE)sb.st_ino; 143 mtp->mode = sb.st_mode; 144 /* 145 * Interpolate a possible file system (mounted-on) device name link. 146 */ 147 if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) 148 goto no_space_for_mount; 149 mtp->fsname = dn; 150 ln = Readlink(dn); 151 dn = (char *)NULL; 152 /* 153 * Stat() the file system (mounted-on) name and add file system 154 * information to the local mount table entry. 155 */ 156 if (!ln || statsafely(ln, &sb)) 157 sb.st_mode = 0; 158 mtp->fsnmres = ln; 159 mtp->fs_mode = sb.st_mode; 160 Lmi = mtp; 161 } 162/* 163 * Clean up and return the local mount info table address. 164 */ 165 if (dn) 166 (void) free((FREE_P *)dn); 167 Lmist = 1; 168 return(Lmi); 169} 170 171 172/* 173 * readvfs() - read vfs structure 174 */ 175 176struct l_vfs * 177readvfs(vm) 178 KA_T vm; /* kernel mount address from vnode */ 179{ 180 struct mount m; 181 struct l_vfs *vp; 182/* 183 * Search for match on existing entry. 184 */ 185 for (vp = Lvfs; vp; vp = vp->next) { 186 if (vm == vp->addr) 187 return(vp); 188 } 189/* 190 * Read the (new) mount structure, allocate a local entry, and fill it. 191 */ 192 if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0) 193 return((struct l_vfs *)NULL); 194 if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { 195 (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", 196 Pn, Lp->pid); 197 Exit(1); 198 } 199 if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL)) 200 || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL))) 201 { 202 (void) fprintf(stderr, "%s: PID %d, no space for mount names\n", 203 Pn, Lp->pid); 204 Exit(1); 205 } 206 vp->addr = vm; 207 vp->fsid = m.m_stat.f_fsid; 208 { 209 int len; 210 211 if ((len = strlen(m.m_stat.f_fstypename))) { 212 if (len > (MFSNAMELEN - 1)) 213 len = MFSNAMELEN - 1; 214 if (!(vp->typnm = mkstrcat(m.m_stat.f_fstypename, len, 215 (char *)NULL, -1, (char *)NULL, -1, 216 (MALLOC_S *)NULL))) 217 { 218 (void) fprintf(stderr, 219 "%s: no space for fs type name: ", Pn); 220 safestrprt(m.m_stat.f_fstypename, stderr, 1); 221 Exit(1); 222 } 223 } else 224 vp->typnm = ""; 225 } 226 vp->next = Lvfs; 227 Lvfs = vp; 228 return(vp); 229} 230