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