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